diff options
author | Alexander Radchenko <radchenkosasha@gmail.com> | 2018-04-10 04:40:29 +0300 |
---|---|---|
committer | Ahson Khan <ahkha@microsoft.com> | 2018-04-10 04:40:29 +0300 |
commit | bd301664af514f39fc3b4b84c5eb257aae3c011b (patch) | |
tree | 7aff8af208dede19b716de5e1edda762add04736 /src | |
parent | 3ad8ce59dd3203f8a72febf5c5e56c742de49fad (diff) |
Created tests for default and empty ReadOnlySequence (#28702)
* Created tests for default and empty ReadOnlySequence
* using
* Added comments
* Renamed method ThrowArgumentValidationException to ThrowStartOrEndArgumentValidationException
* Splitted tests for Empty and Default into separated files
* Review issues
* Added brackets
Diffstat (limited to 'src')
7 files changed, 548 insertions, 99 deletions
diff --git a/src/System.Memory/src/System/Buffers/ReadOnlySequence.cs b/src/System.Memory/src/System/Buffers/ReadOnlySequence.cs index 58c1518d82..1184e2212b 100644 --- a/src/System.Memory/src/System/Buffers/ReadOnlySequence.cs +++ b/src/System.Memory/src/System/Buffers/ReadOnlySequence.cs @@ -68,8 +68,10 @@ namespace System.Buffers private ReadOnlySequence(object startSegment, int startIndexAndFlags, object endSegment, int endIndexAndFlags) { // Used by SliceImpl to create new ReadOnlySequence - Debug.Assert(startSegment != null); - Debug.Assert(endSegment != null); + + // startSegment and endSegment can be null for default ReadOnlySequence only + Debug.Assert( (startSegment != null && endSegment != null) || + (startSegment == null && endSegment == null && startIndexAndFlags == 0 && endIndexAndFlags == 0) ); _sequenceStart = new SequencePosition(startSegment, startIndexAndFlags); _sequenceEnd = new SequencePosition(endSegment, endIndexAndFlags); @@ -160,6 +162,9 @@ namespace System.Buffers /// <param name="length">The length of the slice</param> public ReadOnlySequence<T> Slice(long start, long length) { + if (start < 0 || length < 0) + ThrowHelper.ThrowStartOrEndArgumentValidationException(start); + SequencePosition begin = Seek(_sequenceStart, _sequenceEnd, start); SequencePosition end = Seek(begin, _sequenceEnd, length); return SliceImpl(begin, end); @@ -172,6 +177,8 @@ namespace System.Buffers /// <param name="end">The end (inclusive) of the slice</param> public ReadOnlySequence<T> Slice(long start, SequencePosition end) { + if (start < 0) + ThrowHelper.ThrowStartOrEndArgumentValidationException(start); BoundsCheck(end, _sequenceEnd); SequencePosition begin = Seek(_sequenceStart, end, start); @@ -191,7 +198,10 @@ namespace System.Buffers /// <param name="length">The length of the slice</param> public ReadOnlySequence<T> Slice(SequencePosition start, long length) { - BoundsCheck(start, _sequenceEnd); + BoundsCheck(start, _sequenceEnd); // check start before length + if (length < 0) + // Passing value >= 0 means throw exception on length argument + ThrowHelper.ThrowStartOrEndArgumentValidationException(0); SequencePosition end = Seek(start, _sequenceEnd, length); return SliceImpl(start, end); @@ -204,6 +214,9 @@ namespace System.Buffers /// <param name="length">The length of the slice</param> public ReadOnlySequence<T> Slice(int start, int length) { + if (start < 0 || length < 0) + ThrowHelper.ThrowStartOrEndArgumentValidationException(start); + SequencePosition begin = Seek(_sequenceStart, _sequenceEnd, start); SequencePosition end = Seek(begin, _sequenceEnd, length); return SliceImpl(begin, end); @@ -216,6 +229,8 @@ namespace System.Buffers /// <param name="end">The end (inclusive) of the slice</param> public ReadOnlySequence<T> Slice(int start, SequencePosition end) { + if (start < 0) + ThrowHelper.ThrowStartOrEndArgumentValidationException(start); BoundsCheck(end, _sequenceEnd); SequencePosition begin = Seek(_sequenceStart, end, start); @@ -235,7 +250,10 @@ namespace System.Buffers /// <param name="length">The length of the slice</param> public ReadOnlySequence<T> Slice(SequencePosition start, int length) { - BoundsCheck(start, _sequenceEnd); + BoundsCheck(start, _sequenceEnd); // check start before length + if (length < 0) + // Passing value >= 0 means throw exception on length argument + ThrowHelper.ThrowStartOrEndArgumentValidationException(0); SequencePosition end = Seek(start, _sequenceEnd, length); return SliceImpl(start, end); @@ -271,10 +289,11 @@ namespace System.Buffers /// <param name="start">The start index at which to begin this slice.</param> public ReadOnlySequence<T> Slice(long start) { + if (start < 0) + ThrowHelper.ThrowStartOrEndArgumentValidationException(start); + if (start == 0) - { return this; - } SequencePosition begin = Seek(_sequenceStart, _sequenceEnd, start); return SliceImpl(begin, _sequenceEnd); @@ -330,7 +349,7 @@ namespace System.Buffers public SequencePosition GetPosition(long offset, SequencePosition origin) { if (offset < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.offset); + ThrowHelper.ThrowArgumentOutOfRangeException_OffsetOutOfRange(); return Seek(origin, _sequenceEnd, offset); } diff --git a/src/System.Memory/src/System/Buffers/ReadOnlySequence_helpers.cs b/src/System.Memory/src/System/Buffers/ReadOnlySequence_helpers.cs index f3f40bf838..b1c5569c65 100644 --- a/src/System.Memory/src/System/Buffers/ReadOnlySequence_helpers.cs +++ b/src/System.Memory/src/System/Buffers/ReadOnlySequence_helpers.cs @@ -142,10 +142,10 @@ namespace System.Buffers } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal SequencePosition Seek(in SequencePosition start, in SequencePosition end, int count) => Seek(start, end, (long)count); + internal SequencePosition Seek(in SequencePosition start, in SequencePosition end, int offset) => Seek(start, end, (long)offset); [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal SequencePosition Seek(in SequencePosition start, in SequencePosition end, long count) + internal SequencePosition Seek(in SequencePosition start, in SequencePosition end, long offset) { GetTypeAndIndices(start.GetInteger(), end.GetInteger(), out SequenceType type, out int startIndex, out int endIndex); @@ -160,48 +160,48 @@ namespace System.Buffers int currentLength = startSegment.Memory.Length - startIndex; // Position in start segment, defer to single segment seek - if (currentLength > count) + if (currentLength > offset) goto IsSingleSegment; // End of segment. Move to start of next. - return SeekMultiSegment(startSegment.Next, startIndex, endObject, endIndex, count - currentLength); + return SeekMultiSegment(startSegment.Next, endObject, endIndex, offset - currentLength); } Debug.Assert(startObject == endObject); - if (endIndex - startIndex < count) - ThrowHelper.ThrowArgumentOutOfRangeException_CountOutOfRange(); + if (endIndex - startIndex < offset) + ThrowHelper.ThrowArgumentOutOfRangeException_OffsetOutOfRange(); // Single segment Seek IsSingleSegment: - return new SequencePosition(startObject, startIndex + (int)count); + return new SequencePosition(startObject, startIndex + (int)offset); } [MethodImpl(MethodImplOptions.NoInlining)] - private static SequencePosition SeekMultiSegment(ReadOnlySequenceSegment<T> currentSegment, int startIndex, object endObject, int endPosition, long count) + private static SequencePosition SeekMultiSegment(ReadOnlySequenceSegment<T> currentSegment, object endObject, int endPosition, long offset) { Debug.Assert(currentSegment != null); - Debug.Assert(count >= 0); + Debug.Assert(offset >= 0); while (currentSegment != null && currentSegment != endObject) { int memoryLength = currentSegment.Memory.Length; // Fully contained in this segment - if (memoryLength > count) + if (memoryLength > offset) goto FoundSegment; // Move to next - count -= memoryLength; + offset -= memoryLength; currentSegment = currentSegment.Next; } // Hit the end of the segments but didn't reach the count - if (currentSegment == null || (currentSegment == endObject && endPosition < count)) - ThrowHelper.ThrowArgumentOutOfRangeException_CountOutOfRange(); + if (currentSegment == null || (currentSegment == endObject && endPosition < offset)) + ThrowHelper.ThrowArgumentOutOfRangeException_OffsetOutOfRange(); FoundSegment: - return new SequencePosition(currentSegment, (int)count); + return new SequencePosition(currentSegment, (int)offset); } private static void CheckEndReachable(object startSegment, object endSegment) diff --git a/src/System.Memory/src/System/ThrowHelper.cs b/src/System.Memory/src/System/ThrowHelper.cs index f72d712f35..5a854a49b3 100644 --- a/src/System.Memory/src/System/ThrowHelper.cs +++ b/src/System.Memory/src/System/ThrowHelper.cs @@ -80,9 +80,9 @@ namespace System [MethodImpl(MethodImplOptions.NoInlining)] private static Exception CreateArgumentOutOfRangeException_PositionOutOfRange() { return new ArgumentOutOfRangeException("position"); } - internal static void ThrowArgumentOutOfRangeException_CountOutOfRange() { throw CreateArgumentOutOfRangeException_CountOutOfRange(); } + internal static void ThrowArgumentOutOfRangeException_OffsetOutOfRange() { throw CreateArgumentOutOfRangeException_OffsetOutOfRange(); } [MethodImpl(MethodImplOptions.NoInlining)] - private static Exception CreateArgumentOutOfRangeException_CountOutOfRange() { return new ArgumentOutOfRangeException("count"); } + private static Exception CreateArgumentOutOfRangeException_OffsetOutOfRange() { return new ArgumentOutOfRangeException(nameof(ExceptionArgument.offset)); } internal static void ThrowObjectDisposedException_ArrayMemoryPoolBuffer() { throw CreateObjectDisposedException_ArrayMemoryPoolBuffer(); } [MethodImpl(MethodImplOptions.NoInlining)] @@ -151,6 +151,20 @@ namespace System else return CreateArgumentOutOfRangeException(ExceptionArgument.length); } + + // + // ReadOnlySequence Slice validation Throws coalesced to enable inlining of the Slice + // + public static void ThrowStartOrEndArgumentValidationException(long start) + => throw CreateStartOrEndArgumentValidationException(start); + + private static Exception CreateStartOrEndArgumentValidationException(long start) + { + if (start < 0) + return CreateArgumentOutOfRangeException(ExceptionArgument.start); + return CreateArgumentOutOfRangeException(ExceptionArgument.length); + } + } // diff --git a/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.Common.cs b/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.Common.cs index 25cb2da0af..7cfa2d1c18 100644 --- a/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.Common.cs +++ b/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.Common.cs @@ -5,7 +5,6 @@ using System.Buffers; using System.Collections.Generic; using System.Linq; -using System.MemoryTests; using System.Text; using Xunit; @@ -13,6 +12,8 @@ namespace System.Memory.Tests { public class CommonReadOnlySequenceTests { + #region Position + [Fact] public void SegmentStartIsConsideredInBoundsCheck() { @@ -103,6 +104,10 @@ namespace System.Memory.Tests Assert.Equal(200, seq.Length); } + #endregion + + #region First + [Fact] public void CanGetFirst() { @@ -141,6 +146,10 @@ namespace System.Memory.Tests Assert.Equal(0, buffer.First.Length); } + #endregion + + #region EmptySegments + [Fact] public void SeekSkipsEmptySegments() { @@ -183,6 +192,62 @@ namespace System.Memory.Tests } [Fact] + public void SeekEmptySkipDoesNotCrossPastEnd() + { + var bufferSegment1 = new BufferSegment<byte>(new byte[100]); + BufferSegment<byte> bufferSegment2 = bufferSegment1.Append(new byte[0]); + BufferSegment<byte> bufferSegment3 = bufferSegment2.Append(new byte[0]); + BufferSegment<byte> bufferSegment4 = bufferSegment3.Append(new byte[100]); + + var buffer = new ReadOnlySequence<byte>(bufferSegment1, 0, bufferSegment2, 0); + + SequencePosition c1 = buffer.GetPosition(100); + + Assert.Equal(0, c1.GetInteger()); + Assert.Equal(bufferSegment2, c1.GetObject()); + + c1 = buffer.GetPosition(100, buffer.Start); + + Assert.Equal(0, c1.GetInteger()); + Assert.Equal(bufferSegment2, c1.GetObject()); + + // Go out of bounds for segment + Assert.Throws<ArgumentOutOfRangeException>(() => c1 = buffer.GetPosition(150, buffer.Start)); + Assert.Throws<ArgumentOutOfRangeException>(() => c1 = buffer.GetPosition(250, buffer.Start)); + } + + [Fact] + public void SeekEmptySkipDoesNotCrossPastEndWithExtraChainedBlocks() + { + var bufferSegment1 = new BufferSegment<byte>(new byte[100]); + BufferSegment<byte> bufferSegment2 = bufferSegment1.Append(new byte[0]); + BufferSegment<byte> bufferSegment3 = bufferSegment2.Append(new byte[0]); + BufferSegment<byte> bufferSegment4 = bufferSegment3.Append(new byte[100]); + BufferSegment<byte> bufferSegment5 = bufferSegment4.Append(new byte[0]); + BufferSegment<byte> bufferSegment6 = bufferSegment5.Append(new byte[100]); + + var buffer = new ReadOnlySequence<byte>(bufferSegment1, 0, bufferSegment2, 0); + + SequencePosition c1 = buffer.GetPosition(100); + + Assert.Equal(0, c1.GetInteger()); + Assert.Equal(bufferSegment2, c1.GetObject()); + + c1 = buffer.GetPosition(100, buffer.Start); + + Assert.Equal(0, c1.GetInteger()); + Assert.Equal(bufferSegment2, c1.GetObject()); + + // Go out of bounds for segment + Assert.Throws<ArgumentOutOfRangeException>(() => c1 = buffer.GetPosition(150, buffer.Start)); + Assert.Throws<ArgumentOutOfRangeException>(() => c1 = buffer.GetPosition(250, buffer.Start)); + } + + #endregion + + #region TryGet + + [Fact] public void TryGetStopsAtEnd() { var bufferSegment1 = new BufferSegment<byte>(new byte[100]); @@ -211,8 +276,8 @@ namespace System.Memory.Tests var buffer = new ReadOnlySequence<byte>(bufferSegment1, 0, bufferSegment1, 100); - var start = buffer.Start; - Assert.True(buffer.TryGet(ref start, out var memory)); + SequencePosition start = buffer.Start; + Assert.True(buffer.TryGet(ref start, out ReadOnlyMemory<byte> memory)); Assert.Equal(100, memory.Length); Assert.False(buffer.TryGet(ref start, out memory)); } @@ -225,8 +290,8 @@ namespace System.Memory.Tests var buffer = new ReadOnlySequence<byte>(bufferSegment1, 0, bufferSegment2, 0); - var start = buffer.Start; - Assert.True(buffer.TryGet(ref start, out var memory)); + SequencePosition start = buffer.Start; + Assert.True(buffer.TryGet(ref start, out ReadOnlyMemory<byte> memory)); Assert.Equal(100, memory.Length); Assert.True(buffer.TryGet(ref start, out memory)); Assert.Equal(0, memory.Length); @@ -241,14 +306,18 @@ namespace System.Memory.Tests var buffer = new ReadOnlySequence<byte>(bufferSegment1, 0, bufferSegment2, 0); - var start = buffer.Start; - Assert.True(buffer.TryGet(ref start, out var memory)); + SequencePosition start = buffer.Start; + Assert.True(buffer.TryGet(ref start, out ReadOnlyMemory<byte> memory)); Assert.Equal(100, memory.Length); Assert.True(buffer.TryGet(ref start, out memory)); Assert.Equal(0, memory.Length); Assert.False(buffer.TryGet(ref start, out memory)); } + #endregion + + #region Enumerable + [Fact] public void EnumerableStopsAtEndWhenEndIsLastByteOfFull() { @@ -258,7 +327,7 @@ namespace System.Memory.Tests var buffer = new ReadOnlySequence<byte>(bufferSegment1, 0, bufferSegment1, 100); List<int> sizes = new List<int>(); - foreach (var memory in buffer) + foreach (ReadOnlyMemory<byte> memory in buffer) { sizes.Add(memory.Length); } @@ -276,7 +345,7 @@ namespace System.Memory.Tests var buffer = new ReadOnlySequence<byte>(bufferSegment1, 0, bufferSegment2, 0); List<int> sizes = new List<int>(); - foreach (var memory in buffer) + foreach (ReadOnlyMemory<byte> memory in buffer) { sizes.Add(memory.Length); } @@ -294,7 +363,7 @@ namespace System.Memory.Tests var buffer = new ReadOnlySequence<byte>(bufferSegment1, 0, bufferSegment2, 0); List<int> sizes = new List<int>(); - foreach (var memory in buffer) + foreach (ReadOnlyMemory<byte> memory in buffer) { sizes.Add(memory.Length); } @@ -303,73 +372,9 @@ namespace System.Memory.Tests Assert.Equal(new[] { 100, 0 }, sizes); } - [Fact] - public void SeekEmptySkipDoesNotCrossPastEnd() - { - var bufferSegment1 = new BufferSegment<byte>(new byte[100]); - BufferSegment<byte> bufferSegment2 = bufferSegment1.Append(new byte[0]); - BufferSegment<byte> bufferSegment3 = bufferSegment2.Append(new byte[0]); - BufferSegment<byte> bufferSegment4 = bufferSegment3.Append(new byte[100]); + #endregion - var buffer = new ReadOnlySequence<byte>(bufferSegment1, 0, bufferSegment2, 0); - - SequencePosition c1 = buffer.GetPosition(100); - - Assert.Equal(0, c1.GetInteger()); - Assert.Equal(bufferSegment2, c1.GetObject()); - - c1 = buffer.GetPosition(100, buffer.Start); - - Assert.Equal(0, c1.GetInteger()); - Assert.Equal(bufferSegment2, c1.GetObject()); - - // Go out of bounds for segment - Assert.Throws<ArgumentOutOfRangeException>(() => c1 = buffer.GetPosition(150, buffer.Start)); - Assert.Throws<ArgumentOutOfRangeException>(() => c1 = buffer.GetPosition(250, buffer.Start)); - } - - [Fact] - public void SeekEmptySkipDoesNotCrossPastEndWithExtraChainedBlocks() - { - var bufferSegment1 = new BufferSegment<byte>(new byte[100]); - BufferSegment<byte> bufferSegment2 = bufferSegment1.Append(new byte[0]); - BufferSegment<byte> bufferSegment3 = bufferSegment2.Append(new byte[0]); - BufferSegment<byte> bufferSegment4 = bufferSegment3.Append(new byte[100]); - BufferSegment<byte> bufferSegment5 = bufferSegment4.Append(new byte[0]); - BufferSegment<byte> bufferSegment6 = bufferSegment5.Append(new byte[100]); - - var buffer = new ReadOnlySequence<byte>(bufferSegment1, 0, bufferSegment2, 0); - - SequencePosition c1 = buffer.GetPosition(100); - - Assert.Equal(0, c1.GetInteger()); - Assert.Equal(bufferSegment2, c1.GetObject()); - - c1 = buffer.GetPosition(100, buffer.Start); - - Assert.Equal(0, c1.GetInteger()); - Assert.Equal(bufferSegment2, c1.GetObject()); - - // Go out of bounds for segment - Assert.Throws<ArgumentOutOfRangeException>(() => c1 = buffer.GetPosition(150, buffer.Start)); - Assert.Throws<ArgumentOutOfRangeException>(() => c1 = buffer.GetPosition(250, buffer.Start)); - } - - [Fact] - public void Create_WorksWithArray() - { - var buffer = new ReadOnlySequence<byte>(new byte[] { 1, 2, 3, 4, 5 }); - Assert.Equal(buffer.ToArray(), new byte[] { 1, 2, 3, 4, 5 }); - } - - [Fact] - public void Empty_ReturnsLengthZeroBuffer() - { - var buffer = ReadOnlySequence<byte>.Empty; - Assert.Equal(0, buffer.Length); - Assert.Equal(true, buffer.IsSingleSegment); - Assert.Equal(0, buffer.First.Length); - } + #region Constructor [Fact] public void Ctor_Array_Offset() @@ -418,6 +423,8 @@ namespace System.Memory.Tests Assert.Throws<ArgumentNullException>(() => new ReadOnlySequence<byte>(segment, 5, null, 0)); } + #endregion + [Fact] public void HelloWorldAcrossTwoBlocks() { diff --git a/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.Default.cs b/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.Default.cs new file mode 100644 index 0000000000..b2d5ddc892 --- /dev/null +++ b/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.Default.cs @@ -0,0 +1,191 @@ +// 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.Buffers; +using Xunit; + +namespace System.Memory.Tests +{ + public class ReadOnlySequenceTestsDefault + { + #region Constructor + + [Fact] + public void Default_Constructor() + { + ReadOnlySequence<byte> buffer = default; + Assert.Equal(default, buffer.Start); + Assert.Equal(default, buffer.End); + Assert.True(buffer.IsEmpty); + Assert.True(buffer.IsSingleSegment); + Assert.Equal(0, buffer.Length); + Assert.True(buffer.First.IsEmpty); + Assert.Equal($"System.Buffers.ReadOnlySequence<{typeof(byte).Name}>[0]", buffer.ToString()); + } + + #endregion + + #region GetPosition + + [Fact] + public void Default_GetPosition() + { + ReadOnlySequence<byte> buffer = default; + SequencePosition position = default; + + Assert.Equal(position, buffer.GetPosition(0)); + Assert.Equal(position, buffer.GetPosition(0, buffer.Start)); + Assert.Equal(position, buffer.GetPosition(0, buffer.End)); + } + + [Fact] + public void Default_GetPositionPositive() + { + ReadOnlySequence<byte> buffer = default; + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(1)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(1, buffer.Start)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(1, buffer.End)); + } + + [Fact] + public void Default_GetPositionNegative() + { + ReadOnlySequence<byte> buffer = default; + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(-1)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(-1, buffer.Start)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(-1, buffer.End)); + } + + #endregion + + #region Slice + + [Fact] + public void Default_Slice() + { + ReadOnlySequence<byte> buffer = default; + Assert.Equal(buffer, buffer.Slice(0, 0)); + Assert.Equal(buffer, buffer.Slice(0, buffer.End)); + Assert.Equal(buffer, buffer.Slice(0)); + Assert.Equal(buffer, buffer.Slice(0L, 0L)); + Assert.Equal(buffer, buffer.Slice(0L, buffer.End)); + Assert.Equal(buffer, buffer.Slice(buffer.Start)); + Assert.Equal(buffer, buffer.Slice(buffer.Start, 0)); + Assert.Equal(buffer, buffer.Slice(buffer.Start, 0L)); + Assert.Equal(buffer, buffer.Slice(buffer.Start, buffer.End)); + } + + [Fact] + public void Default_SlicePositiveStart() + { + ReadOnlySequence<byte> buffer = default; + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1, 0)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1, 0)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1, buffer.End)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1L, 0L)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1L, buffer.End)); + } + + [Fact] + public void Default_SliceNegativeStart() + { + ReadOnlySequence<byte> buffer = default; + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1, 0)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1, -1)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1, buffer.End)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1L, 0L)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1L, -1L)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1L, buffer.End)); + } + + [Fact] + public void Default_SlicePositiveLength() + { + ReadOnlySequence<byte> buffer = default; + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(0, 1)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(0L, 1L)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(buffer.Start, 1)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(buffer.Start, 1L)); + } + + [Fact] + public void Default_SliceNegativeLength() + { + ReadOnlySequence<byte> buffer = default; + Assert.Throws<ArgumentOutOfRangeException>("length", () => buffer.Slice(0, -1)); + Assert.Throws<ArgumentOutOfRangeException>("length", () => buffer.Slice(0L, -1L)); + Assert.Throws<ArgumentOutOfRangeException>("length", () => buffer.Slice(buffer.Start, -1)); + Assert.Throws<ArgumentOutOfRangeException>("length", () => buffer.Slice(buffer.Start, -1L)); + } + + #endregion + + #region Enumerator + + [Fact] + public void Default_Enumerator() + { + ReadOnlySequence<byte> buffer = default; + ReadOnlySequence<byte>.Enumerator enumerator = buffer.GetEnumerator(); + { + Assert.Equal(default, enumerator.Current); + Assert.False(enumerator.MoveNext()); + } + enumerator = new ReadOnlySequence<byte>.Enumerator(default); + { + Assert.Equal(default, enumerator.Current); + Assert.False(enumerator.MoveNext()); + } + } + + #endregion + + #region TryGet + + [Fact] + public void Default_TryGet() + { + ReadOnlySequence<byte> buffer = default; + ReadOnlyMemory<byte> memory; + + SequencePosition c1 = buffer.Start; + Assert.False(buffer.TryGet(ref c1, out memory, false)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, true)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, false)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, true)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + c1 = buffer.End; + Assert.False(buffer.TryGet(ref c1, out memory, false)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, true)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, false)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, true)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + } + + #endregion + } +} diff --git a/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.Empty.cs b/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.Empty.cs new file mode 100644 index 0000000000..164c9727dc --- /dev/null +++ b/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.Empty.cs @@ -0,0 +1,216 @@ +// 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.Buffers; +using Xunit; + +namespace System.Memory.Tests +{ + public class ReadOnlySequenceTestsEmpty + { + #region Constructor + + [Fact] + public void Empty_Constructor() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + Assert.Equal(buffer.Start.GetObject(), buffer.End.GetObject()); + Assert.Equal(0, buffer.Start.GetInteger() & int.MaxValue); + Assert.Equal(0, buffer.End.GetInteger() & int.MaxValue); + Assert.True(buffer.IsEmpty); + Assert.True(buffer.IsSingleSegment); + Assert.Equal(0, buffer.Length); + Assert.True(buffer.First.IsEmpty); + Assert.Equal($"System.Buffers.ReadOnlySequence<{typeof(byte).Name}>[0]", buffer.ToString()); + } + + #endregion + + #region GetPosition + + [Fact] + public void Empty_GetPosition() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + SequencePosition position = new SequencePosition(buffer.Start.GetObject(), 0); + + Assert.Equal(position, buffer.GetPosition(0)); + Assert.Equal(position, buffer.GetPosition(0, buffer.Start)); + Assert.Equal(position, buffer.GetPosition(0, buffer.End)); + } + + [Fact] + public void Empty_GetPositionPositive() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(1)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(1, buffer.Start)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(1, buffer.End)); + } + + [Fact] + public void Empty_GetPositionNegative() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(-1)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(-1, buffer.Start)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.GetPosition(-1, buffer.End)); + } + + #endregion + + #region Slice + + [Fact] + public void Empty_Slice() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + Assert.Equal(buffer, buffer.Slice(0, 0)); + Assert.Equal(buffer, buffer.Slice(0, buffer.End)); + Assert.Equal(buffer, buffer.Slice(0)); + Assert.Equal(buffer, buffer.Slice(0L, 0L)); + Assert.Equal(buffer, buffer.Slice(0L, buffer.End)); + Assert.Equal(buffer, buffer.Slice(buffer.Start)); + Assert.Equal(buffer, buffer.Slice(buffer.Start, 0)); + Assert.Equal(buffer, buffer.Slice(buffer.Start, 0L)); + Assert.Equal(buffer, buffer.Slice(buffer.Start, buffer.End)); + } + + [Fact] + public void Empty_SlicePositiveStart() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1, 0)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1, 0)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1, buffer.End)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1L, 0L)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(1L, buffer.End)); + } + + [Fact] + public void Empty_SliceNegativeStart() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1, 0)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1, -1)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1, buffer.End)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1L, 0L)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1L, -1L)); + Assert.Throws<ArgumentOutOfRangeException>("start", () => buffer.Slice(-1L, buffer.End)); + } + + [Fact] + public void Empty_SlicePositiveLength() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(0, 1)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(0L, 1L)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(buffer.Start, 1)); + Assert.Throws<ArgumentOutOfRangeException>("offset", () => buffer.Slice(buffer.Start, 1L)); + } + + [Fact] + public void Empty_SliceNegativeLength() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + Assert.Throws<ArgumentOutOfRangeException>("length", () => buffer.Slice(0, -1)); + Assert.Throws<ArgumentOutOfRangeException>("length", () => buffer.Slice(0L, -1L)); + Assert.Throws<ArgumentOutOfRangeException>("length", () => buffer.Slice(buffer.Start, -1)); + Assert.Throws<ArgumentOutOfRangeException>("length", () => buffer.Slice(buffer.Start, -1L)); + } + + #endregion + + #region Enumerator + + [Fact] + public void Empty_Enumerator() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + ReadOnlySequence<byte>.Enumerator enumerator = buffer.GetEnumerator(); + { + Assert.Equal(default, enumerator.Current); + Assert.True(enumerator.MoveNext()); + ReadOnlyMemory<byte> memory = enumerator.Current; + Assert.True(memory.IsEmpty); + + Assert.False(enumerator.MoveNext()); + } + enumerator = new ReadOnlySequence<byte>.Enumerator(buffer); + { + Assert.Equal(default, enumerator.Current); + Assert.True(enumerator.MoveNext()); + ReadOnlyMemory<byte> memory = enumerator.Current; + Assert.True(memory.IsEmpty); + + Assert.False(enumerator.MoveNext()); + } + } + + #endregion + + #region TryGet + + [Fact] + public void Empty_TryGet() + { + ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty; + ReadOnlyMemory<byte> memory; + + SequencePosition c1 = buffer.Start; + Assert.True(buffer.TryGet(ref c1, out memory, false)); + Assert.Equal(buffer.Start, c1); + Assert.True(memory.IsEmpty); + + Assert.True(buffer.TryGet(ref c1, out memory, true)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, false)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, true)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, false)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, true)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + c1 = buffer.End; + Assert.True(buffer.TryGet(ref c1, out memory, false)); + Assert.Equal(buffer.End, c1); + Assert.True(memory.IsEmpty); + + Assert.True(buffer.TryGet(ref c1, out memory, true)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, false)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, true)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, false)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + + Assert.False(buffer.TryGet(ref c1, out memory, true)); + Assert.Equal(null, c1.GetObject()); + Assert.True(memory.IsEmpty); + } + + #endregion + } +} diff --git a/src/System.Memory/tests/System.Memory.Tests.csproj b/src/System.Memory/tests/System.Memory.Tests.csproj index fa92304b23..d9bbbf699e 100644 --- a/src/System.Memory/tests/System.Memory.Tests.csproj +++ b/src/System.Memory/tests/System.Memory.Tests.csproj @@ -20,6 +20,8 @@ </ItemGroup> <ItemGroup> <Compile Include="AllocationHelper.cs" /> + <Compile Include="ReadOnlyBuffer\ReadOnlySequenceTests.Default.cs" /> + <Compile Include="ReadOnlyBuffer\ReadOnlySequenceTests.Empty.cs" /> <Compile Include="TInt.cs" /> <Compile Include="TestException.cs" /> <Compile Include="TestHelpers.cs" /> |