< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Runtime.BufferedOutputStream
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Runtime/BufferedOutputStream.cs
Line coverage
79%
Covered lines: 85
Uncovered lines: 22
Coverable lines: 107
Total lines: 322
Line coverage: 79.4%
Branch coverage
75%
Covered branches: 24
Total branches: 32
Branch coverage: 75%
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%11100%
.ctor(...)100%11100%
Reinitialize(...)100%11100%
Reinitialize(...)100%11100%
AllocNextChunk(...)83.33%6692.85%
ReadAsync(...)100%110%
WriteAsync(...)100%11100%
Clear()100%44100%
Flush()100%11100%
Read(...)100%110%
ReadByte()100%110%
Seek(...)100%110%
SetLength(...)100%110%
ToMemoryStream()100%110%
ToArray(...)100%44100%
Skip(...)100%11100%
Write(...)100%11100%
CreateQuotaExceededException(...)100%110%
WriteCore(...)78.57%141485.71%
WriteByte(...)0%440%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/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;
 8
 9namespace CoreWCF.Runtime
 10{
 11    internal class BufferedOutputStream : Stream
 12    {
 13        private InternalBufferManager _bufferManager;
 14        private byte[][] _chunks;
 15        private int _chunkCount;
 16        private byte[] _currentChunk;
 17        private int _currentChunkSize;
 18        private int _maxSize;
 19        private int _maxSizeQuota;
 20        private int _totalSize;
 21        private bool _callerReturnsBuffer;
 22        private bool _bufferReturned;
 23        private bool _initialized;
 24
 25        // requires an explicit call to Init() by the caller
 368026        public BufferedOutputStream()
 27        {
 368028            _chunks = new byte[4][];
 368029        }
 30
 315431        public BufferedOutputStream(int initialSize, int maxSize, InternalBufferManager bufferManager) : this()
 32        {
 315433            Reinitialize(initialSize, maxSize, bufferManager);
 315434        }
 35
 36        public BufferedOutputStream(int maxSize)
 137            : this(0, maxSize, InternalBufferManager.Create(0, int.MaxValue))
 38        {
 139        }
 40
 41        public override bool CanRead
 42        {
 43            get
 44            {
 045                return false;
 46            }
 47        }
 48
 49        public override bool CanSeek
 50        {
 51            get
 52            {
 053                return false;
 54            }
 55        }
 56
 57        public override bool CanWrite
 58        {
 59            get
 60            {
 1061                return true;
 62            }
 63        }
 64
 65        public override long Length
 66        {
 67            get
 68            {
 1848469                return _totalSize;
 70            }
 71        }
 72
 73        public override long Position
 74        {
 75            get
 76            {
 077                throw Fx.Exception.AsError(new NotSupportedException(SR.SeekNotSupported));
 78            }
 79            set
 80            {
 081                throw Fx.Exception.AsError(new NotSupportedException(SR.SeekNotSupported));
 82            }
 83        }
 84
 85        public void Reinitialize(int initialSize, int maxSizeQuota, InternalBufferManager bufferManager)
 86        {
 315487            Reinitialize(initialSize, maxSizeQuota, maxSizeQuota, bufferManager);
 315488        }
 89
 90        public void Reinitialize(int initialSize, int maxSizeQuota, int effectiveMaxSize, InternalBufferManager bufferMa
 91        {
 92            Fx.Assert(!_initialized, "Clear must be called before re-initializing stream");
 392893            _maxSizeQuota = maxSizeQuota;
 392894            _maxSize = effectiveMaxSize;
 392895            _bufferManager = bufferManager;
 392896            _currentChunk = bufferManager.TakeBuffer(initialSize);
 392897            _currentChunkSize = 0;
 392898            _totalSize = 0;
 392899            _chunkCount = 1;
 3928100            _chunks[0] = _currentChunk;
 3928101            _initialized = true;
 3928102        }
 103
 104        private void AllocNextChunk(int minimumChunkSize)
 105        {
 106            int newChunkSize;
 1779107            if (_currentChunk.Length > (int.MaxValue / 2))
 108            {
 0109                newChunkSize = int.MaxValue;
 110            }
 111            else
 112            {
 1779113                newChunkSize = _currentChunk.Length * 2;
 114            }
 1779115            if (minimumChunkSize > newChunkSize)
 116            {
 5117                newChunkSize = minimumChunkSize;
 118            }
 1779119            byte[] newChunk = _bufferManager.TakeBuffer(newChunkSize);
 1779120            if (_chunkCount == _chunks.Length)
 121            {
 238122                byte[][] newChunks = new byte[_chunks.Length * 2][];
 238123                Array.Copy(_chunks, newChunks, _chunks.Length);
 238124                _chunks = newChunks;
 125            }
 1779126            _chunks[_chunkCount++] = newChunk;
 1779127            _currentChunk = newChunk;
 1779128            _currentChunkSize = 0;
 1779129        }
 130
 131        public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 132        {
 0133            return Task.FromException<int>(Fx.Exception.AsError(new NotSupportedException(SR.ReadNotSupported)));
 134        }
 135
 136        //public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object sta
 137        //{
 138        //    throw Fx.Exception.AsError(new NotSupportedException(SR.ReadNotSupported));
 139        //}
 140
 141        //public override int EndRead(IAsyncResult result)
 142        //{
 143        //    throw Fx.Exception.AsError(new NotSupportedException(SR.ReadNotSupported));
 144        //}
 145
 146        public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 147        {
 10148            Write(buffer, offset, count);
 10149            return Task.CompletedTask;
 150        }
 151
 152        //public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object st
 153        //{
 154        //    Write(buffer, offset, size);
 155        //    return new CompletedAsyncResult(callback, state);
 156        //}
 157
 158        //public override void EndWrite(IAsyncResult result)
 159        //{
 160        //    CompletedAsyncResult.End(result);
 161        //}
 162
 163        public void Clear()
 164        {
 774165            if (!_callerReturnsBuffer)
 166            {
 2022167                for (int i = 0; i < _chunkCount; i++)
 168                {
 764169                    _bufferManager.ReturnBuffer(_chunks[i]);
 764170                    _chunks[i] = null;
 171                }
 172            }
 173
 774174            _callerReturnsBuffer = false;
 774175            _initialized = false;
 774176            _bufferReturned = false;
 774177            _chunkCount = 0;
 774178            _currentChunk = null;
 774179        }
 180
 181        //public override void Close()
 182        //{
 183        //}
 184
 185        public override void Flush()
 186        {
 20762187        }
 188
 189        public override int Read(byte[] buffer, int offset, int size)
 190        {
 0191            throw Fx.Exception.AsError(new NotSupportedException(SR.ReadNotSupported));
 192        }
 193
 194        public override int ReadByte()
 195        {
 0196            throw Fx.Exception.AsError(new NotSupportedException(SR.ReadNotSupported));
 197        }
 198
 199        public override long Seek(long offset, SeekOrigin origin)
 200        {
 0201            throw Fx.Exception.AsError(new NotSupportedException(SR.SeekNotSupported));
 202        }
 203
 204        public override void SetLength(long value)
 205        {
 0206            throw Fx.Exception.AsError(new NotSupportedException(SR.SeekNotSupported));
 207        }
 208
 209        public MemoryStream ToMemoryStream()
 210        {
 0211            byte[] buffer = ToArray(out int bufferSize);
 0212            return new MemoryStream(buffer, 0, bufferSize);
 213        }
 214
 215        public byte[] ToArray(out int bufferSize)
 216        {
 217            Fx.Assert(_initialized, "No data to return from uninitialized stream");
 218            Fx.Assert(!_bufferReturned, "ToArray cannot be called more than once");
 219
 220            byte[] buffer;
 3928221            if (_chunkCount == 1)
 222            {
 3212223                buffer = _currentChunk;
 3212224                bufferSize = _currentChunkSize;
 3212225                _callerReturnsBuffer = true;
 226            }
 227            else
 228            {
 716229                buffer = _bufferManager.TakeBuffer(_totalSize);
 716230                int offset = 0;
 716231                int count = _chunkCount - 1;
 4990232                for (int i = 0; i < count; i++)
 233                {
 1779234                    byte[] chunk = _chunks[i];
 1779235                    Buffer.BlockCopy(chunk, 0, buffer, offset, chunk.Length);
 1779236                    offset += chunk.Length;
 237                }
 716238                Buffer.BlockCopy(_currentChunk, 0, buffer, offset, _currentChunkSize);
 716239                bufferSize = _totalSize;
 240            }
 241
 3928242            _bufferReturned = true;
 3928243            return buffer;
 244        }
 245
 246        public void Skip(int size)
 247        {
 779248            WriteCore(null, 0, size);
 779249        }
 250
 251        public override void Write(byte[] buffer, int offset, int size)
 252        {
 161946253            WriteCore(buffer, offset, size);
 161946254        }
 255
 256        protected virtual Exception CreateQuotaExceededException(int maxSizeQuota)
 257        {
 0258            return new InvalidOperationException(SR.Format(SR.BufferedOutputStreamQuotaExceeded, maxSizeQuota));
 259        }
 260
 261        private void WriteCore(byte[] buffer, int offset, int size)
 262        {
 263            Fx.Assert(_initialized, "Cannot write to uninitialized stream");
 264            Fx.Assert(!_bufferReturned, "Cannot write to stream once ToArray has been called.");
 265
 162725266            if (size < 0)
 267            {
 0268                throw Fx.Exception.ArgumentOutOfRange(nameof(size), size, SRCommon.ValueMustBeNonNegative);
 269            }
 270
 162725271            if ((int.MaxValue - size) < _totalSize)
 272            {
 0273                throw Fx.Exception.AsError(CreateQuotaExceededException(_maxSizeQuota));
 274            }
 275
 162725276            int newTotalSize = _totalSize + size;
 162725277            if (newTotalSize > _maxSize)
 278            {
 0279                throw Fx.Exception.AsError(CreateQuotaExceededException(_maxSizeQuota));
 280            }
 281
 162725282            int remainingSizeInChunk = _currentChunk.Length - _currentChunkSize;
 162725283            if (size > remainingSizeInChunk)
 284            {
 1779285                if (remainingSizeInChunk > 0)
 286                {
 1762287                    if (buffer != null)
 288                    {
 1762289                        Buffer.BlockCopy(buffer, offset, _currentChunk, _currentChunkSize, remainingSizeInChunk);
 290                    }
 1762291                    _currentChunkSize = _currentChunk.Length;
 1762292                    offset += remainingSizeInChunk;
 1762293                    size -= remainingSizeInChunk;
 294                }
 1779295                AllocNextChunk(size);
 296            }
 297
 162725298            if (buffer != null)
 299            {
 161946300                Buffer.BlockCopy(buffer, offset, _currentChunk, _currentChunkSize, size);
 301            }
 162725302            _totalSize = newTotalSize;
 162725303            _currentChunkSize += size;
 162725304        }
 305
 306        public override void WriteByte(byte value)
 307        {
 308            Fx.Assert(_initialized, "Cannot write to uninitialized stream");
 309            Fx.Assert(!_bufferReturned, "Cannot write to stream once ToArray has been called.");
 310
 0311            if (_totalSize == _maxSize)
 312            {
 0313                throw Fx.Exception.AsError(CreateQuotaExceededException(_maxSize));
 314            }
 0315            if (_currentChunkSize == _currentChunk.Length)
 316            {
 0317                AllocNextChunk(1);
 318            }
 0319            _currentChunk[_currentChunkSize++] = value;
 0320        }
 321    }
 322}