< Summary

Class:Azure.Core.Pipeline.ReadTimeoutStream
Assembly:Azure.Core
File(s):C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Pipeline\Internal\ReadTimeoutStream.cs
Covered lines:33
Uncovered lines:27
Coverable lines:60
Total lines:159
Line coverage:55% (33 of 60)
Covered branches:3
Total branches:6
Branch coverage:50% (3 of 6)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor(...)-100%100%
Read(...)-0%100%
ReadAsync()-57.14%100%
StartTimeout(...)-66.67%50%
InitializeTokenSource()-100%100%
DisposeStream()-100%100%
StopTimeout(...)-75%50%
Seek(...)-0%100%
get_CanRead()-100%100%
get_CanSeek()-100%100%
get_Length()-0%100%
get_Position()-0%100%
set_Position(...)-0%100%
get_ReadTimeout()-0%100%
set_ReadTimeout(...)-0%100%
UpdateReadTimeout()-100%100%
Close()-100%100%
Dispose(...)-0%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Pipeline\Internal\ReadTimeoutStream.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.IO;
 6using System.Threading;
 7using System.Threading.Tasks;
 8
 9namespace Azure.Core.Pipeline
 10{
 11    /// <summary>
 12    /// Read-only Stream that will throw a <see cref="OperationCanceledException"/> if it has to wait longer than a conf
 13    /// </summary>
 14    internal class ReadTimeoutStream : ReadOnlyStream
 15    {
 16        private readonly Stream _stream;
 17        private TimeSpan _readTimeout;
 18        private CancellationTokenSource _cancellationTokenSource = null!;
 19
 162020        public ReadTimeoutStream(Stream stream, TimeSpan readTimeout)
 21        {
 162022            _stream = stream;
 162023            _readTimeout = readTimeout;
 162024            UpdateReadTimeout();
 162025            InitializeTokenSource();
 162026        }
 27
 28        public override int Read(byte[] buffer, int offset, int count)
 29        {
 030            var source = StartTimeout(default, out bool dispose);
 31            try
 32            {
 033                return _stream.Read(buffer, offset, count);
 34            }
 35            // We dispose stream on timeout so catch and check if cancellation token was cancelled
 036            catch (ObjectDisposedException)
 37            {
 038                source.Token.ThrowIfCancellationRequested();
 039                throw;
 40            }
 41            finally
 42            {
 043                StopTimeout(source, dispose);
 044            }
 045        }
 46
 47        public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationTo
 48        {
 680449            var source = StartTimeout(cancellationToken, out bool dispose);
 50            try
 51            {
 680452                return await _stream.ReadAsync(buffer, offset, count, source.Token).ConfigureAwait(false);
 53            }
 54            // We dispose stream on timeout so catch and check if cancellation token was cancelled
 055            catch (ObjectDisposedException)
 56            {
 057                source.Token.ThrowIfCancellationRequested();
 058                throw;
 59            }
 60            finally
 61            {
 680462                StopTimeout(source, dispose);
 63            }
 679264        }
 65
 66        private CancellationTokenSource StartTimeout(CancellationToken additionalToken, out bool dispose)
 67        {
 680468            if (_cancellationTokenSource.IsCancellationRequested)
 69            {
 070                InitializeTokenSource();
 71            }
 72
 73            CancellationTokenSource source;
 680474            if (additionalToken.CanBeCanceled)
 75            {
 076                source = CancellationTokenSource.CreateLinkedTokenSource(additionalToken, _cancellationTokenSource.Token
 077                dispose = true;
 78            }
 79            else
 80            {
 680481                source = _cancellationTokenSource;
 680482                dispose = false;
 83            }
 84
 680485            _cancellationTokenSource.CancelAfter(_readTimeout);
 86
 680487            return source;
 88        }
 89
 90        private void InitializeTokenSource()
 91        {
 162092            _cancellationTokenSource = new CancellationTokenSource();
 163293            _cancellationTokenSource.Token.Register(() => DisposeStream());
 162094        }
 95
 96        private void DisposeStream()
 97        {
 1298            _stream.Dispose();
 1299        }
 100
 101        private void StopTimeout(CancellationTokenSource source, bool dispose)
 102        {
 6804103            _cancellationTokenSource.CancelAfter(Timeout.InfiniteTimeSpan);
 6804104            if (dispose)
 105            {
 0106                source.Dispose();
 107            }
 6804108        }
 109
 110        public override long Seek(long offset, SeekOrigin origin)
 111        {
 0112            return _stream.Seek(offset, origin);
 113        }
 114
 1204115        public override bool CanRead => _stream.CanRead;
 4012116        public override bool CanSeek => _stream.CanSeek;
 0117        public override long Length => _stream.Length;
 118
 119        public override long Position
 120        {
 0121            get => _stream.Position;
 0122            set => _stream.Position = value;
 123        }
 124
 125        public override int ReadTimeout
 126        {
 0127            get => (int) _readTimeout.TotalMilliseconds;
 128            set
 129            {
 0130                _readTimeout = TimeSpan.FromMilliseconds(value);
 0131                UpdateReadTimeout();
 0132            }
 133        }
 134
 135        private void UpdateReadTimeout()
 136        {
 137            try
 138            {
 1620139                _stream.ReadTimeout = (int) _readTimeout.TotalMilliseconds;
 12140            }
 1608141            catch
 142            {
 143                // ignore
 1608144            }
 1620145        }
 146
 147        public override void Close()
 148        {
 1196149            _stream.Close();
 1196150        }
 151
 152        protected override void Dispose(bool disposing)
 153        {
 0154            base.Dispose(disposing);
 0155            _stream.Dispose();
 0156            _cancellationTokenSource.Dispose();
 0157        }
 158    }
 159}