Improve test coverage for SequenceReader. (dotnet/corefx#37416)
authorJeremy Kuhne <jkuhne@microsoft.com>
Wed, 15 May 2019 19:08:19 +0000 (12:08 -0700)
committerGitHub <noreply@github.com>
Wed, 15 May 2019 19:08:19 +0000 (12:08 -0700)
One of the tests was inadvertently private. Added additional coverage and clarification text to TryCopyTo.

Commit migrated from https://github.com/dotnet/corefx/commit/203f61e27e93b098dcc0736fbfe2b38528dcf9aa

src/libraries/System.Memory/src/System/Buffers/SequenceReader.cs
src/libraries/System.Memory/tests/SequenceReader/Advance.cs
src/libraries/System.Memory/tests/SequenceReader/CopyTo.cs [new file with mode: 0644]
src/libraries/System.Memory/tests/SequenceReader/IsNext.cs
src/libraries/System.Memory/tests/SequenceReader/Rewind.cs
src/libraries/System.Memory/tests/SequenceReader/SkipDelimiter.cs
src/libraries/System.Memory/tests/System.Memory.Tests.csproj

index 52a24e3..824b67b 100644 (file)
@@ -147,10 +147,13 @@ namespace System.Buffers
         /// <summary>
         /// Move the reader back the specified number of items.
         /// </summary>
+        /// <exception cref="ArgumentOutOfRangeException">
+        /// Thrown if trying to rewind a negative amount or more than <see cref="Consumed"/>.
+        /// </exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void Rewind(long count)
         {
-            if (count < 0)
+            if (count < 0 || count > Consumed)
             {
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count);
             }
@@ -324,13 +327,22 @@ namespace System.Buffers
         }
 
         /// <summary>
-        /// Copies data from the current <see cref="Position"/> to the given <paramref name="destination"/> span.
+        /// Copies data from the current <see cref="Position"/> to the given <paramref name="destination"/> span if there
+        /// is enough data to fill it.
         /// </summary>
-        /// <param name="destination">Destination to copy to.</param>
-        /// <returns>True if there is enough data to copy to the <paramref name="destination"/>.</returns>
+        /// <remarks>
+        /// This API is used to copy a fixed amount of data out of the sequence if possible. It does not advance
+        /// the reader. To look ahead for a specific stream of data <see cref="IsNext(ReadOnlySpan{T}, bool)"/> can be used.
+        /// </remarks>
+        /// <param name="destination">Destination span to copy to.</param>
+        /// <returns>True if there is enough data to completely fill the <paramref name="destination"/> span.</returns>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool TryCopyTo(Span<T> destination)
         {
+            // This API doesn't advance to facilitate conditional advancement based on the data returned.
+            // We don't provide an advance option to allow easier utilizing of stack allocated destination spans.
+            // (Because we can make this method readonly we can guarantee that we won't capture the span.)
+
             ReadOnlySpan<T> firstSpan = UnreadSpan;
             if (firstSpan.Length >= destination.Length)
             {
@@ -338,11 +350,13 @@ namespace System.Buffers
                 return true;
             }
 
+            // Not enough in the current span to satisfy the request, fall through to the slow path
             return TryCopyMultisegment(destination);
         }
 
         internal bool TryCopyMultisegment(Span<T> destination)
         {
+            // If we don't have enough to fill the requested buffer, return false
             if (Remaining < destination.Length)
                 return false;
 
index 5ac2253..89430bb 100644 (file)
@@ -37,6 +37,21 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(3, skipReader.AdvancePastAny(new byte[] { 2, 3, 1 }));
             Assert.True(skipReader.TryRead(out value));
             Assert.Equal(4, value);
+            skipReader.Rewind(skipReader.Consumed);
+            Assert.Equal(0, skipReader.AdvancePast(2));
+            Assert.Equal(3, skipReader.AdvancePastAny(2, 3, 1));
+            Assert.True(skipReader.TryRead(out value));
+            Assert.Equal(4, value);
+            skipReader.Rewind(skipReader.Consumed);
+            Assert.Equal(0, skipReader.AdvancePast(2));
+            Assert.Equal(3, skipReader.AdvancePastAny(2, 3, 1, 7));
+            Assert.True(skipReader.TryRead(out value));
+            Assert.Equal(4, value);
+            skipReader.Rewind(skipReader.Consumed - 1);
+            Assert.Equal(0, skipReader.AdvancePast(1));
+            Assert.Equal(2, skipReader.AdvancePastAny(2, 3));
+            Assert.True(skipReader.TryRead(out value));
+            Assert.Equal(4, value);
         }
 
         [Fact]
diff --git a/src/libraries/System.Memory/tests/SequenceReader/CopyTo.cs b/src/libraries/System.Memory/tests/SequenceReader/CopyTo.cs
new file mode 100644 (file)
index 0000000..3ef90c9
--- /dev/null
@@ -0,0 +1,64 @@
+// 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.Buffers;
+using Xunit;
+
+namespace System.Memory.Tests.SequenceReader
+{
+    public class CopyTo
+    {
+        [Fact]
+        public void TryCopyTo_Empty()
+        {
+            var reader = new SequenceReader<char>(ReadOnlySequence<char>.Empty);
+
+            // Nothing to nothing is always possible
+            Assert.True(reader.TryCopyTo(Span<char>.Empty));
+
+            // Nothing to something doesn't work
+            Assert.False(reader.TryCopyTo(new char[1]));
+        }
+
+        [Fact]
+        public void TryCopyTo_Multisegment()
+        {
+            ReadOnlySequence<char> chars = SequenceFactory.Create(new char[][] {
+                new char[] { 'A'           },
+                new char[] { 'B', 'C'      },
+                new char[] { 'D', 'E', 'F' }
+            });
+
+            ReadOnlySpan<char> linear = new char[] { 'A', 'B', 'C', 'D', 'E', 'F' };
+
+            var reader = new SequenceReader<char>(chars);
+
+            // Something to nothing is always possible
+            Assert.True(reader.TryCopyTo(Span<char>.Empty));
+            Span<char> buffer;
+
+            // Read out ABCDEF, ABCDE, etc.
+            for (int i = linear.Length; i > 0; i--)
+            {
+                buffer = new char[i];
+                Assert.True(reader.TryCopyTo(buffer));
+                Assert.True(buffer.SequenceEqual(linear.Slice(0, i)));
+            }
+
+            buffer = new char[1];
+
+            // Read out one at a time and move through
+            for (int i = 0; i < linear.Length; i++)
+            {
+                Assert.True(reader.TryCopyTo(buffer));
+                Assert.True(reader.TryRead(out char value));
+                Assert.Equal(buffer[0], value);
+            }
+
+            // Trying to get more data than there is will fail
+            Assert.False(reader.TryCopyTo(new char[reader.Remaining + 1]));
+        }
+    }
+}
index 8141de4..6742539 100644 (file)
@@ -9,6 +9,25 @@ namespace System.Memory.Tests.SequenceReader
 {
     public class IsNext
     {
+        [Theory,
+            InlineData(true),
+            InlineData(false)]
+        public void IsNext_Empty(bool advancePast)
+        {
+            var reader = new SequenceReader<char>(ReadOnlySequence<char>.Empty);
+
+            Assert.False(reader.IsNext('Z', advancePast));
+            Assert.Equal(0, reader.Consumed);
+
+            // Nothing is always next
+            Assert.True(reader.IsNext(ReadOnlySpan<char>.Empty, advancePast));
+            Assert.Equal(0, reader.Consumed);
+
+            // Something isn't
+            Assert.False(reader.IsNext(new char[] { '\0' }, advancePast));
+            Assert.Equal(0, reader.Consumed);
+        }
+
         [Fact]
         public void IsNext_Span()
         {
@@ -19,7 +38,7 @@ namespace System.Memory.Tests.SequenceReader
                 new byte[] { 5, 6, 7, 8 }
             });
 
-            SequenceReader<byte> reader = new SequenceReader<byte>(bytes);
+            var reader = new SequenceReader<byte>(bytes);
             Assert.True(reader.IsNext(ReadOnlySpan<byte>.Empty, advancePast: false));
             Assert.True(reader.IsNext(ReadOnlySpan<byte>.Empty, advancePast: true));
             Assert.True(reader.IsNext(new byte[] { 0 }, advancePast: false));
@@ -41,6 +60,28 @@ namespace System.Memory.Tests.SequenceReader
             Assert.True(reader.IsNext(new byte[] { 4, 5, 6 }, advancePast: true));
             Assert.True(reader.TryPeek(out byte value));
             Assert.Equal(7, value);
+
+            Assert.True(reader.IsNext(new byte[] { 7, 8 }, advancePast: true));
+            Assert.True(reader.End);
+        }
+
+        [Fact]
+        public void IsNext_Value()
+        {
+            ReadOnlySequence<char> chars = SequenceFactory.Create(new char[][] {
+                new char[] { 'A'           },
+                new char[] { 'B', 'C'      },
+            });
+
+            var reader = new SequenceReader<char>(chars);
+            Assert.False(reader.IsNext('Z', advancePast: false));
+            Assert.False(reader.IsNext('B', advancePast: false));
+            Assert.True(reader.IsNext('A', advancePast: false));
+            Assert.True(reader.IsNext('A', advancePast: true));
+            Assert.True(reader.IsNext('B', advancePast: true));
+            Assert.True(reader.IsNext('C', advancePast: true));
+            Assert.False(reader.IsNext('C', advancePast: true));
+            Assert.True(reader.End);
         }
     }
 }
index bd31301..45d8da2 100644 (file)
@@ -72,13 +72,32 @@ namespace System.Memory.Tests.SequenceReader
         public void Rewind_Exception()
         {
             ReadOnlySequence<byte> bytes = SequenceFactory.Create(new byte[][] {
-                new byte[] { 0          },
-                new byte[] { 1, 2       },
-                new byte[] { 3, 4       },
-                new byte[] { 5, 6, 7, 8 }
+                new byte[] { 0    },
+                new byte[] { 1, 2 }
             });
 
+            // Can't go negative
             Assert.Throws<ArgumentOutOfRangeException>(() => new SequenceReader<byte>(bytes).Rewind(-1));
+
+            // Can't pull more than we consumed
+            Assert.Throws<ArgumentOutOfRangeException>(() => new SequenceReader<byte>(bytes).Rewind(1));
+        }
+
+        [Fact]
+        public void RewindEmptyFirstSpan()
+        {
+            // This is to hit the "if (memory.Length == 0)" branch in ResetReader.
+            ReadOnlySequence<byte> bytes = SequenceFactory.Create(new byte[][] {
+                new byte[0],
+                new byte[] { 1, 2 },
+                new byte[] { 3, 4 }
+            });
+
+            var reader = new SequenceReader<byte>(bytes);
+            reader.Advance(3);
+            Assert.True(reader.IsNext(4));
+            reader.Rewind(2);
+            Assert.Equal(new byte[] { 1, 2 }, reader.CurrentSpan.ToArray());
         }
     }
 }
index ec10205..4c56c49 100644 (file)
@@ -8,7 +8,7 @@ using Xunit;
 
 namespace System.Memory.Tests.SequenceReader
 {
-    class SkipDelimiter
+    public class SkipDelimiter
     {
         [Fact]
         public void TryReadTo_SkipDelimiter()
@@ -20,12 +20,22 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(expected, span.ToArray());
             Assert.True(reader.IsNext((byte)' '));
             Assert.Equal(30, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out ReadOnlySequence<byte> sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
+            Assert.Equal(expected, sequence.ToArray());
+            Assert.True(reader.IsNext((byte)' '));
+            Assert.Equal(30, reader.Consumed);
 
             reader = new SequenceReader<byte>(bytes);
             Assert.True(reader.TryReadTo(out span, (byte)'|', (byte)'^', advancePastDelimiter: false));
             Assert.Equal(expected, span.ToArray());
             Assert.True(reader.IsNext((byte)'|'));
             Assert.Equal(29, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.Equal(expected, sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'|'));
+            Assert.Equal(29, reader.Consumed);
 
             // Put the skip delimiter in another segment
             bytes = SequenceFactory.CreateUtf8("This is our ^|understanding", "^|| you see.");
@@ -34,12 +44,22 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(expected, span.ToArray());
             Assert.True(reader.IsNext((byte)' '));
             Assert.Equal(30, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
+            Assert.Equal(expected, sequence.ToArray());
+            Assert.True(reader.IsNext((byte)' '));
+            Assert.Equal(30, reader.Consumed);
 
             reader = new SequenceReader<byte>(bytes);
             Assert.True(reader.TryReadTo(out span, (byte)'|', (byte)'^', advancePastDelimiter: false));
             Assert.Equal(expected, span.ToArray());
             Assert.True(reader.IsNext((byte)'|'));
             Assert.Equal(29, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.Equal(expected, sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'|'));
+            Assert.Equal(29, reader.Consumed);
 
             // Put the skip delimiter at the end of the segment
             bytes = SequenceFactory.CreateUtf8("This is our ^|understanding^", "|| you see.");
@@ -48,12 +68,22 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(expected, span.ToArray());
             Assert.True(reader.IsNext((byte)' '));
             Assert.Equal(30, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
+            Assert.Equal(expected, sequence.ToArray());
+            Assert.True(reader.IsNext((byte)' '));
+            Assert.Equal(30, reader.Consumed);
 
             reader = new SequenceReader<byte>(bytes);
             Assert.True(reader.TryReadTo(out span, (byte)'|', (byte)'^', advancePastDelimiter: false));
             Assert.Equal(expected, span.ToArray());
             Assert.True(reader.IsNext((byte)'|'));
             Assert.Equal(29, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.Equal(expected, sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'|'));
+            Assert.Equal(29, reader.Consumed);
 
             // No trailing data
             bytes = SequenceFactory.CreateUtf8("This is our ^|understanding^||");
@@ -62,22 +92,36 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(expected, span.ToArray());
             Assert.True(reader.IsNext((byte)'|'));
             Assert.Equal(29, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.Equal(expected, sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'|'));
+            Assert.Equal(29, reader.Consumed);
 
             reader = new SequenceReader<byte>(bytes);
             Assert.True(reader.TryReadTo(out span, (byte)'|', (byte)'^', advancePastDelimiter: true));
             Assert.Equal(expected, span.ToArray());
             Assert.True(reader.End);
             Assert.Equal(30, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
+            Assert.Equal(expected, sequence.ToArray());
+            Assert.True(reader.End);
+            Assert.Equal(30, reader.Consumed);
 
             // All delimiters skipped
             bytes = SequenceFactory.CreateUtf8("This is our ^|understanding^|");
             reader = new SequenceReader<byte>(bytes);
             Assert.False(reader.TryReadTo(out span, (byte)'|', (byte)'^', advancePastDelimiter: false));
             Assert.Equal(0, reader.Consumed);
+            Assert.False(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.Equal(0, reader.Consumed);
 
             reader = new SequenceReader<byte>(bytes);
             Assert.False(reader.TryReadTo(out span, (byte)'|', (byte)'^', advancePastDelimiter: true));
             Assert.Equal(0, reader.Consumed);
+            Assert.False(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
+            Assert.Equal(0, reader.Consumed);
 
             bytes = SequenceFactory.CreateUtf8("abc^|de|");
             reader = new SequenceReader<byte>(bytes);
@@ -85,6 +129,11 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(Encoding.UTF8.GetBytes("abc^|de"), span.ToArray());
             Assert.True(reader.End);
             Assert.Equal(8, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
+            Assert.Equal(Encoding.UTF8.GetBytes("abc^|de"), sequence.ToArray());
+            Assert.True(reader.End);
+            Assert.Equal(8, reader.Consumed);
 
             // Escape leads
             bytes = SequenceFactory.CreateUtf8("^|a|b");
@@ -93,6 +142,11 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(Encoding.UTF8.GetBytes("^|a"), span.ToArray());
             Assert.True(reader.IsNext((byte)'b'));
             Assert.Equal(4, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
+            Assert.Equal(Encoding.UTF8.GetBytes("^|a"), sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'b'));
+            Assert.Equal(4, reader.Consumed);
 
             // Delimiter starts second segment.
             bytes = SequenceFactory.CreateUtf8("^", "|a|b");
@@ -101,6 +155,11 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(Encoding.UTF8.GetBytes("^|a"), span.ToArray());
             Assert.True(reader.IsNext((byte)'b'));
             Assert.Equal(4, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
+            Assert.Equal(Encoding.UTF8.GetBytes("^|a"), sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'b'));
+            Assert.Equal(4, reader.Consumed);
         }
 
         [Fact]
@@ -112,6 +171,11 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(Encoding.UTF8.GetBytes("abc^^"), span.ToArray());
             Assert.True(reader.IsNext((byte)'|'));
             Assert.Equal(5, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out ReadOnlySequence<byte> sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.Equal(Encoding.UTF8.GetBytes("abc^^"), sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'|'));
+            Assert.Equal(5, reader.Consumed);
 
             // Split after escape char
             bytes = SequenceFactory.CreateUtf8("abc^^", "|def");
@@ -120,6 +184,11 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(Encoding.UTF8.GetBytes("abc^^"), span.ToArray());
             Assert.True(reader.IsNext((byte)'|'));
             Assert.Equal(5, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.Equal(Encoding.UTF8.GetBytes("abc^^"), sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'|'));
+            Assert.Equal(5, reader.Consumed);
 
             // Split before and after escape char
             bytes = SequenceFactory.CreateUtf8("abc^", "^", "|def");
@@ -128,6 +197,11 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(Encoding.UTF8.GetBytes("abc^^"), span.ToArray());
             Assert.True(reader.IsNext((byte)'|'));
             Assert.Equal(5, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.Equal(Encoding.UTF8.GetBytes("abc^^"), sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'|'));
+            Assert.Equal(5, reader.Consumed);
 
             // Check advance past delimiter
             reader = new SequenceReader<byte>(bytes);
@@ -135,6 +209,11 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(Encoding.UTF8.GetBytes("abc^^"), span.ToArray());
             Assert.True(reader.IsNext((byte)'d'));
             Assert.Equal(6, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
+            Assert.Equal(Encoding.UTF8.GetBytes("abc^^"), sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'d'));
+            Assert.Equal(6, reader.Consumed);
 
             // Leading run of 2
             bytes = SequenceFactory.CreateUtf8("^^|abc");
@@ -143,6 +222,11 @@ namespace System.Memory.Tests.SequenceReader
             Assert.Equal(Encoding.UTF8.GetBytes("^^"), span.ToArray());
             Assert.True(reader.IsNext((byte)'|'));
             Assert.Equal(2, reader.Consumed);
+            reader.Rewind(reader.Consumed);
+            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.Equal(Encoding.UTF8.GetBytes("^^"), sequence.ToArray());
+            Assert.True(reader.IsNext((byte)'|'));
+            Assert.Equal(2, reader.Consumed);
 
             // Leading run of 3
             bytes = SequenceFactory.CreateUtf8("^^^|abc");
@@ -150,6 +234,9 @@ namespace System.Memory.Tests.SequenceReader
             Assert.False(reader.TryReadTo(out span, (byte)'|', (byte)'^', advancePastDelimiter: false));
             Assert.True(reader.IsNext((byte)'^'));
             Assert.Equal(0, reader.Consumed);
+            Assert.False(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.True(reader.IsNext((byte)'^'));
+            Assert.Equal(0, reader.Consumed);
 
             // Trailing run of 3
             bytes = SequenceFactory.CreateUtf8("abc^^^|");
@@ -157,6 +244,9 @@ namespace System.Memory.Tests.SequenceReader
             Assert.False(reader.TryReadTo(out span, (byte)'|', (byte)'^', advancePastDelimiter: false));
             Assert.True(reader.IsNext((byte)'a'));
             Assert.Equal(0, reader.Consumed);
+            Assert.False(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.True(reader.IsNext((byte)'a'));
+            Assert.Equal(0, reader.Consumed);
 
             // Trailing run of 3, split
             bytes = SequenceFactory.CreateUtf8("abc^^^", "|");
@@ -164,99 +254,9 @@ namespace System.Memory.Tests.SequenceReader
             Assert.False(reader.TryReadTo(out span, (byte)'|', (byte)'^', advancePastDelimiter: false));
             Assert.True(reader.IsNext((byte)'a'));
             Assert.Equal(0, reader.Consumed);
-        }
-
-        [Fact]
-        public void TryReadTo_SkipDelimiter_ReadOnlySequence()
-        {
-            byte[] expected = Encoding.UTF8.GetBytes("This is our ^|understanding^|");
-            ReadOnlySequence<byte> bytes = SequenceFactory.CreateUtf8("This is our ^|understanding^|| you see.");
-            SequenceReader<byte> reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out ReadOnlySequence<byte> sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
-            Assert.Equal(expected, sequence.ToArray());
-            Assert.True(reader.IsNext((byte)' '));
-            Assert.Equal(30, reader.Consumed);
-
-            reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
-            Assert.Equal(expected, sequence.ToArray());
-            Assert.True(reader.IsNext((byte)'|'));
-            Assert.Equal(29, reader.Consumed);
-
-            // Put the skip delimiter in another segment
-            bytes = SequenceFactory.CreateUtf8("This is our ^|understanding", "^|| you see.");
-            reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
-            Assert.Equal(expected, sequence.ToArray());
-            Assert.True(reader.IsNext((byte)' '));
-            Assert.Equal(30, reader.Consumed);
-
-            reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
-            Assert.Equal(expected, sequence.ToArray());
-            Assert.True(reader.IsNext((byte)'|'));
-            Assert.Equal(29, reader.Consumed);
-
-            // Put the skip delimiter at the end of the segment
-            bytes = SequenceFactory.CreateUtf8("This is our ^|understanding^", "|| you see.");
-            reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
-            Assert.Equal(expected, sequence.ToArray());
-            Assert.True(reader.IsNext((byte)' '));
-            Assert.Equal(30, reader.Consumed);
-
-            reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
-            Assert.Equal(expected, sequence.ToArray());
-            Assert.True(reader.IsNext((byte)'|'));
-            Assert.Equal(29, reader.Consumed);
-
-            // No trailing data
-            bytes = SequenceFactory.CreateUtf8("This is our ^|understanding^||");
-            reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
-            Assert.Equal(expected, sequence.ToArray());
-            Assert.True(reader.IsNext((byte)'|'));
-            Assert.Equal(29, reader.Consumed);
-
-            reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
-            Assert.Equal(expected, sequence.ToArray());
-            Assert.True(reader.End);
-            Assert.Equal(30, reader.Consumed);
-
-            // All delimiters skipped
-            bytes = SequenceFactory.CreateUtf8("This is our ^|understanding^|");
-            reader = new SequenceReader<byte>(bytes);
             Assert.False(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: false));
+            Assert.True(reader.IsNext((byte)'a'));
             Assert.Equal(0, reader.Consumed);
-
-            reader = new SequenceReader<byte>(bytes);
-            Assert.False(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
-            Assert.Equal(0, reader.Consumed);
-
-            bytes = SequenceFactory.CreateUtf8("abc^|de|");
-            reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
-            Assert.Equal(Encoding.UTF8.GetBytes("abc^|de"), sequence.ToArray());
-            Assert.True(reader.End);
-            Assert.Equal(8, reader.Consumed);
-
-            // Escape leads
-            bytes = SequenceFactory.CreateUtf8("^|a|b");
-            reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
-            Assert.Equal(Encoding.UTF8.GetBytes("^|a"), sequence.ToArray());
-            Assert.True(reader.IsNext((byte)'b'));
-            Assert.Equal(4, reader.Consumed);
-
-            // Delimiter starts second segment.
-            bytes = SequenceFactory.CreateUtf8("^", "|a|b");
-            reader = new SequenceReader<byte>(bytes);
-            Assert.True(reader.TryReadTo(out sequence, (byte)'|', (byte)'^', advancePastDelimiter: true));
-            Assert.Equal(Encoding.UTF8.GetBytes("^|a"), sequence.ToArray());
-            Assert.True(reader.IsNext((byte)'b'));
-            Assert.Equal(4, reader.Consumed);
         }
     }
 }
index 74eeb41..aaa804e 100644 (file)
@@ -38,6 +38,7 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AllocationHelper.cs" />
+    <Compile Include="SequenceReader\CopyTo.cs" />
     <Compile Include="TInt.cs" />
     <Compile Include="TestException.cs" />
     <Compile Include="TestHelpers.cs" />