// // Copyright (c) Quamotion. All rights reserved. // using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit; namespace plistcil.test { /// /// A which writes its output to a and validates that the data which /// is being written to the output stream matches the data in a reference stream. /// internal class ValidatingStream : Stream { private Stream output; private Stream expectedOutput; /// /// Initializes a new instance of the class. /// /// /// The to which to write data. /// /// /// The reference stream for . /// public ValidatingStream(Stream output, Stream expectedOutput) { this.output = output ?? throw new ArgumentNullException(nameof(output)); this.expectedOutput = expectedOutput ?? throw new ArgumentNullException(nameof(expectedOutput)); } /// public override bool CanRead { get { return false; } } /// public override bool CanSeek { get { return false; } } /// public override bool CanWrite { get { return true; } } /// public override long Length { get { return this.output.Length; } } /// public override long Position { get { return this.output.Position; } set { throw new NotImplementedException(); } } /// public override void Flush() { this.output.Flush(); } /// public override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } /// public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { throw new NotSupportedException(); } /// public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); } /// public override void SetLength(long value) { throw new NotImplementedException(); } /// public override void Write(byte[] buffer, int offset, int count) { byte[] expected = new byte[buffer.Length]; this.expectedOutput.Read(expected, offset, count); byte[] bufferChunk = buffer.Skip(offset).Take(count).ToArray(); byte[] expectedChunk = expected.Skip(offset).Take(count).ToArray(); // Make sure the data being writen matches the data which was written to the expected stream. // This will detect any errors as the invalid data is being written out - as opposed to post- // test binary validation. Assert.Equal(expectedChunk, bufferChunk); this.output.Write(buffer, offset, count); } /// public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { byte[] expected = new byte[buffer.Length]; await this.expectedOutput.ReadAsync(expected, offset, count, cancellationToken).ConfigureAwait(false); byte[] bufferChunk = buffer.Skip(offset).Take(count).ToArray(); byte[] expectedChunk = expected.Skip(offset).Take(count).ToArray(); // Make sure the data being writen matches the data which was written to the expected stream. // This will detect any errors as the invalid data is being written out - as opposed to post- // test binary validation. Assert.Equal(expectedChunk, bufferChunk); await this.output.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); } } }