public void Write()
        {
            MemoryStream innerStream       = new MemoryStream();
            Stream       transcodingStream = Encoding.CreateTranscodingStream(
                innerStream,
                innerStreamEncoding: ErrorCheckingUnicodeEncoding /* throws on error */,
                outerStreamEncoding: Encoding.UTF8 /* performs substition */,
                leaveOpen: true);

            // First, test Write(byte[], int, int)

            transcodingStream.Write(Encoding.UTF8.GetBytes("abcdefg"), 2, 3);
            Assert.Equal("cde", ErrorCheckingUnicodeEncoding.GetString(innerStream.ToArray()));

            // Then test WriteByte(byte)

            transcodingStream.WriteByte((byte)'z');
            Assert.Equal("cdez", ErrorCheckingUnicodeEncoding.GetString(innerStream.ToArray()));

            // We'll write U+00E0 (utf-8: [C3 A0]) byte-by-byte.
            // We shouldn't flush any intermediate bytes.

            transcodingStream.WriteByte((byte)0xC3);
            Assert.Equal("cdez", ErrorCheckingUnicodeEncoding.GetString(innerStream.ToArray()));

            transcodingStream.WriteByte((byte)0xA0);
            Assert.Equal("cdez\u00E0", ErrorCheckingUnicodeEncoding.GetString(innerStream.ToArray()));

            innerStream.SetLength(0); // reset inner stream

            // Then test Write(ROS<byte>), once with a short string and once with a long string

            string asciiString = GetVeryLongAsciiString(128);

            byte[] asciiBytesAsUtf8 = Encoding.UTF8.GetBytes(asciiString);
            transcodingStream.Write(asciiBytesAsUtf8.AsSpan());
            Assert.Equal(asciiString, ErrorCheckingUnicodeEncoding.GetString(innerStream.ToArray()));

            innerStream.SetLength(0); // reset inner stream

            asciiString      = GetVeryLongAsciiString(16 * 1024 * 1024);
            asciiBytesAsUtf8 = Encoding.UTF8.GetBytes(asciiString);
            transcodingStream.Write(asciiBytesAsUtf8.AsSpan());
            Assert.Equal(asciiString, ErrorCheckingUnicodeEncoding.GetString(innerStream.ToArray()));

            innerStream.SetLength(0); // reset inner stream

            // Close the outer stream and ensure no leftover data was written to the inner stream

            transcodingStream.Close();
            Assert.Equal(0, innerStream.Position);
        }
        public async Task WriteAsync()
        {
            MemoryStream      sink = new MemoryStream();
            CancellationToken expectedFlushAsyncCancellationToken = new CancellationTokenSource().Token;
            CancellationToken expectedWriteAsyncCancellationToken = new CancellationTokenSource().Token;

            var innerStreamMock = new Mock <Stream>(MockBehavior.Strict);

            innerStreamMock.Setup(o => o.CanWrite).Returns(true);
            innerStreamMock.Setup(o => o.WriteAsync(It.IsAny <ReadOnlyMemory <byte> >(), expectedWriteAsyncCancellationToken))
            .Returns <ReadOnlyMemory <byte>, CancellationToken>(sink.WriteAsync);
            innerStreamMock.Setup(o => o.FlushAsync(expectedFlushAsyncCancellationToken)).Returns(Task.CompletedTask);

            Stream transcodingStream = Encoding.CreateTranscodingStream(
                innerStreamMock.Object,
                innerStreamEncoding: ErrorCheckingUnicodeEncoding,
                outerStreamEncoding: Encoding.UTF8 /* performs U+FFFD substition */,
                leaveOpen: true);

            // First, test WriteAsync(byte[], int, int, CancellationToken)

            await transcodingStream.WriteAsync(Encoding.UTF8.GetBytes("abcdefg"), 2, 3, expectedWriteAsyncCancellationToken);

            Assert.Equal("cde", ErrorCheckingUnicodeEncoding.GetString(sink.ToArray()));

            // We'll write U+00E0 (utf-8: [C3 A0]) byte-by-byte.
            // We shouldn't flush any intermediate bytes.

            await transcodingStream.WriteAsync(new byte[] { 0xC3, 0xA0 }, 0, 1, expectedWriteAsyncCancellationToken);

            await transcodingStream.FlushAsync(expectedFlushAsyncCancellationToken);

            Assert.Equal("cde", ErrorCheckingUnicodeEncoding.GetString(sink.ToArray()));

            await transcodingStream.WriteAsync(new byte[] { 0xC3, 0xA0 }, 1, 1, expectedWriteAsyncCancellationToken);

            Assert.Equal("cde\u00E0", ErrorCheckingUnicodeEncoding.GetString(sink.ToArray()));

            sink.SetLength(0); // reset sink

            // Then test WriteAsync(ROM<byte>, CancellationToken), once with a short string and once with a long string

            string asciiString = GetVeryLongAsciiString(128);

            byte[] asciiBytesAsUtf8 = Encoding.UTF8.GetBytes(asciiString);
            await transcodingStream.WriteAsync(asciiBytesAsUtf8.AsMemory(), expectedWriteAsyncCancellationToken);

            Assert.Equal(asciiString, ErrorCheckingUnicodeEncoding.GetString(sink.ToArray()));

            sink.SetLength(0); // reset sink

            asciiString      = GetVeryLongAsciiString(16 * 1024 * 1024);
            asciiBytesAsUtf8 = Encoding.UTF8.GetBytes(asciiString);
            await transcodingStream.WriteAsync(asciiBytesAsUtf8.AsMemory(), expectedWriteAsyncCancellationToken);

            Assert.Equal(asciiString, ErrorCheckingUnicodeEncoding.GetString(sink.ToArray()));

            sink.SetLength(0); // reset sink

            // Close the outer stream and ensure no leftover data was written to the inner stream

            ValueTask actualDisposeTask = transcodingStream.DisposeAsync();

            Assert.Equal(default(ValueTask), actualDisposeTask); // should've completed synchronously
            Assert.Equal(0, sink.Position);
        }