Пример #1
0
        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
        }
Пример #2
0
        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)));
        }
        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)));
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        public void SetPositionInsideBufferRange_Read_WillNotReadUnderlyingStreamAgain(int sharedBufSize, Action <Stream, long> setPos)
        {
            var trackingStream = new CallTrackingStream(new MemoryStream());
            var bufferedStream = new BufferedStream(trackingStream, sharedBufSize);

            bufferedStream.Write(Enumerable.Range(0, sharedBufSize * 2).Select(i => (byte)i).ToArray(), 0, sharedBufSize * 2);
            setPos(bufferedStream, 0);

            var readBuf = new byte[sharedBufSize - 1];

            // First half part verification
            byte[] expectedReadBuf = Enumerable.Range(0, sharedBufSize - 1).Select(i => (byte)i).ToArray();

            // Call Read() to fill shared read buffer
            int readBytes = bufferedStream.Read(readBuf, 0, readBuf.Length);

            Assert.Equal(readBuf.Length, readBytes);
            Assert.Equal(sharedBufSize - 1, bufferedStream.Position);
            Assert.Equal(expectedReadBuf, readBuf);
            Assert.Equal(1, trackingStream.TimesCalled(nameof(trackingStream.Read)));

            // Set position inside range of shared read buffer
            for (int pos = 0; pos < sharedBufSize - 1; pos++)
            {
                setPos(bufferedStream, pos);

                readBytes = bufferedStream.Read(readBuf, pos, readBuf.Length - pos);
                Assert.Equal(readBuf.Length - pos, readBytes);
                Assert.Equal(sharedBufSize - 1, bufferedStream.Position);
                Assert.Equal(expectedReadBuf, readBuf);
                // Should not trigger underlying stream's Read()
                Assert.Equal(1, trackingStream.TimesCalled(nameof(trackingStream.Read)));
            }

            Assert.Equal(sharedBufSize - 1, bufferedStream.ReadByte());
            Assert.Equal(sharedBufSize, bufferedStream.Position);
            // Should not trigger underlying stream's Read()
            Assert.Equal(1, trackingStream.TimesCalled(nameof(trackingStream.Read)));

            // Second half part verification
            expectedReadBuf = Enumerable.Range(sharedBufSize, sharedBufSize - 1).Select(i => (byte)i).ToArray();
            // Call Read() to fill shared read buffer
            readBytes = bufferedStream.Read(readBuf, 0, readBuf.Length);
            Assert.Equal(readBuf.Length, readBytes);
            Assert.Equal(sharedBufSize * 2 - 1, bufferedStream.Position);
            Assert.Equal(expectedReadBuf, readBuf);
            Assert.Equal(2, trackingStream.TimesCalled(nameof(trackingStream.Read)));

            // Set position inside range of shared read buffer
            for (int pos = 0; pos < sharedBufSize - 1; pos++)
            {
                setPos(bufferedStream, sharedBufSize + pos);

                readBytes = bufferedStream.Read(readBuf, pos, readBuf.Length - pos);
                Assert.Equal(readBuf.Length - pos, readBytes);
                Assert.Equal(sharedBufSize * 2 - 1, bufferedStream.Position);
                Assert.Equal(expectedReadBuf, readBuf);
                // Should not trigger underlying stream's Read()
                Assert.Equal(2, trackingStream.TimesCalled(nameof(trackingStream.Read)));
            }

            Assert.Equal(sharedBufSize * 2 - 1, bufferedStream.ReadByte());
            Assert.Equal(sharedBufSize * 2, bufferedStream.Position);
            // Should not trigger underlying stream's Read()
            Assert.Equal(2, trackingStream.TimesCalled(nameof(trackingStream.Read)));
        }
Пример #9
0
        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
        }
Пример #10
0
        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)));
        }