< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Runtime.BufferedOutputStream
Assembly: CoreWCF.WebHttp
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.WebHttp/src/CoreWCF/Runtime/BufferedOutputStream.cs
Line coverage
40%
Covered lines: 42
Uncovered lines: 63
Coverable lines: 105
Total lines: 319
Line coverage: 40%
Branch coverage
28%
Covered branches: 9
Total branches: 32
Branch coverage: 28.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor()100%11100%
.ctor(...)100%110%
Reinitialize(...)100%110%
Reinitialize(...)100%11100%
AllocNextChunk(...)0%660%
ReadAsync(...)100%110%
WriteAsync(...)100%110%
Clear()50%4470%
Flush()100%11100%
Read(...)100%110%
ReadByte()100%110%
Seek(...)100%110%
SetLength(...)100%110%
ToMemoryStream()100%110%
ToArray(...)25%4440%
Skip(...)100%11100%
Write(...)100%11100%
CreateQuotaExceededException(...)100%110%
WriteCore(...)42.85%141452.38%
WriteByte(...)0%440%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.WebHttp/src/CoreWCF/Runtime/BufferedOutputStream.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.IO;
 6using System.Threading;
 7using System.Threading.Tasks;
 8using CoreWCF.Channels;
 9
 10namespace CoreWCF.Runtime
 11{
 12    internal class BufferedOutputStream : Stream
 13    {
 14        private BufferManager _bufferManager;
 15        private byte[][] _chunks;
 16        private int _chunkCount;
 17        private byte[] _currentChunk;
 18        private int _currentChunkSize;
 19        private int _maxSize;
 20        private int _maxSizeQuota;
 21        private int _totalSize;
 22        private bool _callerReturnsBuffer;
 23        private bool _bufferReturned;
 24        private bool _initialized;
 25
 26        // requires an explicit call to Init() by the caller
 2427        public BufferedOutputStream()
 28        {
 2429            _chunks = new byte[4][];
 2430        }
 31
 32        public BufferedOutputStream(int initialSize, int maxSize, BufferManager bufferManager)
 033            : this()
 34        {
 035            Reinitialize(initialSize, maxSize, bufferManager);
 036        }
 37
 38        public override bool CanRead
 39        {
 40            get
 41            {
 042                return false;
 43            }
 44        }
 45
 46        public override bool CanSeek
 47        {
 48            get
 49            {
 050                return false;
 51            }
 52        }
 53
 54        public override bool CanWrite
 55        {
 56            get
 57            {
 058                return true;
 59            }
 60        }
 61
 62        public override long Length
 63        {
 64            get
 65            {
 066                return _totalSize;
 67            }
 68        }
 69
 70        public override long Position
 71        {
 72            get
 73            {
 074                throw Fx.Exception.AsError(new NotSupportedException(SR.SeekNotSupported));
 75            }
 76            set
 77            {
 078                throw Fx.Exception.AsError(new NotSupportedException(SR.SeekNotSupported));
 79            }
 80        }
 81
 82        public void Reinitialize(int initialSize, int maxSizeQuota, BufferManager bufferManager)
 83        {
 084            Reinitialize(initialSize, maxSizeQuota, maxSizeQuota, bufferManager);
 085        }
 86
 87        public void Reinitialize(int initialSize, int maxSizeQuota, int effectiveMaxSize, BufferManager bufferManager)
 88        {
 89            Fx.Assert(!_initialized, "Clear must be called before re-initializing stream");
 2490            _maxSizeQuota = maxSizeQuota;
 2491            _maxSize = effectiveMaxSize;
 2492            _bufferManager = bufferManager;
 2493            _currentChunk = bufferManager.TakeBuffer(initialSize);
 2494            _currentChunkSize = 0;
 2495            _totalSize = 0;
 2496            _chunkCount = 1;
 2497            _chunks[0] = _currentChunk;
 2498            _initialized = true;
 2499        }
 100
 101        private void AllocNextChunk(int minimumChunkSize)
 102        {
 103            int newChunkSize;
 0104            if (_currentChunk.Length > (int.MaxValue / 2))
 105            {
 0106                newChunkSize = int.MaxValue;
 107            }
 108            else
 109            {
 0110                newChunkSize = _currentChunk.Length * 2;
 111            }
 0112            if (minimumChunkSize > newChunkSize)
 113            {
 0114                newChunkSize = minimumChunkSize;
 115            }
 0116            byte[] newChunk = _bufferManager.TakeBuffer(newChunkSize);
 0117            if (_chunkCount == _chunks.Length)
 118            {
 0119                byte[][] newChunks = new byte[_chunks.Length * 2][];
 0120                Array.Copy(_chunks, newChunks, _chunks.Length);
 0121                _chunks = newChunks;
 122            }
 0123            _chunks[_chunkCount++] = newChunk;
 0124            _currentChunk = newChunk;
 0125            _currentChunkSize = 0;
 0126        }
 127
 128        public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 129        {
 0130            return Task.FromException<int>(Fx.Exception.AsError(new NotSupportedException(SR.ReadNotSupported)));
 131        }
 132
 133        //public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object sta
 134        //{
 135        //    throw Fx.Exception.AsError(new NotSupportedException(SR.ReadNotSupported));
 136        //}
 137
 138        //public override int EndRead(IAsyncResult result)
 139        //{
 140        //    throw Fx.Exception.AsError(new NotSupportedException(SR.ReadNotSupported));
 141        //}
 142
 143        public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 144        {
 0145            Write(buffer, offset, count);
 0146            return Task.CompletedTask;
 147        }
 148
 149        //public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object st
 150        //{
 151        //    Write(buffer, offset, size);
 152        //    return new CompletedAsyncResult(callback, state);
 153        //}
 154
 155        //public override void EndWrite(IAsyncResult result)
 156        //{
 157        //    CompletedAsyncResult.End(result);
 158        //}
 159
 160        public void Clear()
 161        {
 24162            if (!_callerReturnsBuffer)
 163            {
 0164                for (int i = 0; i < _chunkCount; i++)
 165                {
 0166                    _bufferManager.ReturnBuffer(_chunks[i]);
 0167                    _chunks[i] = null;
 168                }
 169            }
 170
 24171            _callerReturnsBuffer = false;
 24172            _initialized = false;
 24173            _bufferReturned = false;
 24174            _chunkCount = 0;
 24175            _currentChunk = null;
 24176        }
 177
 178        //public override void Close()
 179        //{
 180        //}
 181
 182        public override void Flush()
 183        {
 48184        }
 185
 186        public override int Read(byte[] buffer, int offset, int size)
 187        {
 0188            throw Fx.Exception.AsError(new NotSupportedException(SR.ReadNotSupported));
 189        }
 190
 191        public override int ReadByte()
 192        {
 0193            throw Fx.Exception.AsError(new NotSupportedException(SR.ReadNotSupported));
 194        }
 195
 196        public override long Seek(long offset, SeekOrigin origin)
 197        {
 0198            throw Fx.Exception.AsError(new NotSupportedException(SR.SeekNotSupported));
 199        }
 200
 201        public override void SetLength(long value)
 202        {
 0203            throw Fx.Exception.AsError(new NotSupportedException(SR.SeekNotSupported));
 204        }
 205
 206        public MemoryStream ToMemoryStream()
 207        {
 0208            byte[] buffer = ToArray(out int bufferSize);
 0209            return new MemoryStream(buffer, 0, bufferSize);
 210        }
 211
 212        public byte[] ToArray(out int bufferSize)
 213        {
 214            Fx.Assert(_initialized, "No data to return from uninitialized stream");
 215            Fx.Assert(!_bufferReturned, "ToArray cannot be called more than once");
 216
 217            byte[] buffer;
 24218            if (_chunkCount == 1)
 219            {
 24220                buffer = _currentChunk;
 24221                bufferSize = _currentChunkSize;
 24222                _callerReturnsBuffer = true;
 223            }
 224            else
 225            {
 0226                buffer = _bufferManager.TakeBuffer(_totalSize);
 0227                int offset = 0;
 0228                int count = _chunkCount - 1;
 0229                for (int i = 0; i < count; i++)
 230                {
 0231                    byte[] chunk = _chunks[i];
 0232                    Buffer.BlockCopy(chunk, 0, buffer, offset, chunk.Length);
 0233                    offset += chunk.Length;
 234                }
 0235                Buffer.BlockCopy(_currentChunk, 0, buffer, offset, _currentChunkSize);
 0236                bufferSize = _totalSize;
 237            }
 238
 24239            _bufferReturned = true;
 24240            return buffer;
 241        }
 242
 243        public void Skip(int size)
 244        {
 24245            WriteCore(null, 0, size);
 24246        }
 247
 248        public override void Write(byte[] buffer, int offset, int size)
 249        {
 24250            WriteCore(buffer, offset, size);
 24251        }
 252
 253        protected virtual Exception CreateQuotaExceededException(int maxSizeQuota)
 254        {
 0255            return new InvalidOperationException(SR.Format(SR.BufferedOutputStreamQuotaExceeded, maxSizeQuota));
 256        }
 257
 258        private void WriteCore(byte[] buffer, int offset, int size)
 259        {
 260            Fx.Assert(_initialized, "Cannot write to uninitialized stream");
 261            Fx.Assert(!_bufferReturned, "Cannot write to stream once ToArray has been called.");
 262
 48263            if (size < 0)
 264            {
 0265                throw Fx.Exception.ArgumentOutOfRange(nameof(size), size, SRCommon.ValueMustBeNonNegative);
 266            }
 267
 48268            if ((int.MaxValue - size) < _totalSize)
 269            {
 0270                throw Fx.Exception.AsError(CreateQuotaExceededException(_maxSizeQuota));
 271            }
 272
 48273            int newTotalSize = _totalSize + size;
 48274            if (newTotalSize > _maxSize)
 275            {
 0276                throw Fx.Exception.AsError(CreateQuotaExceededException(_maxSizeQuota));
 277            }
 278
 48279            int remainingSizeInChunk = _currentChunk.Length - _currentChunkSize;
 48280            if (size > remainingSizeInChunk)
 281            {
 0282                if (remainingSizeInChunk > 0)
 283                {
 0284                    if (buffer != null)
 285                    {
 0286                        Buffer.BlockCopy(buffer, offset, _currentChunk, _currentChunkSize, remainingSizeInChunk);
 287                    }
 0288                    _currentChunkSize = _currentChunk.Length;
 0289                    offset += remainingSizeInChunk;
 0290                    size -= remainingSizeInChunk;
 291                }
 0292                AllocNextChunk(size);
 293            }
 294
 48295            if (buffer != null)
 296            {
 24297                Buffer.BlockCopy(buffer, offset, _currentChunk, _currentChunkSize, size);
 298            }
 48299            _totalSize = newTotalSize;
 48300            _currentChunkSize += size;
 48301        }
 302
 303        public override void WriteByte(byte value)
 304        {
 305            Fx.Assert(_initialized, "Cannot write to uninitialized stream");
 306            Fx.Assert(!_bufferReturned, "Cannot write to stream once ToArray has been called.");
 307
 0308            if (_totalSize == _maxSize)
 309            {
 0310                throw Fx.Exception.AsError(CreateQuotaExceededException(_maxSize));
 311            }
 0312            if (_currentChunkSize == _currentChunk.Length)
 313            {
 0314                AllocNextChunk(1);
 315            }
 0316            _currentChunk[_currentChunkSize++] = value;
 0317        }
 318    }
 319}