public virtual void FlushAsync_DuringWriteAsync()
        {
            byte[] buffer = new byte[100000];
            Random rand   = new Random();

            rand.NextBytes(buffer);

            using (var writeStream = new ManualSyncMemoryStream(false))
                using (var compressor = CreateStream(writeStream, CompressionMode.Compress))
                {
                    Task task = null;
                    try
                    {
                        // Write needs to be big enough to trigger a write to the underlying base stream so the WriteAsync call doesn't immediately complete.
                        task = compressor.WriteAsync(buffer, 0, buffer.Length);
                        while (task.IsCompleted)
                        {
                            rand.NextBytes(buffer);
                            task = compressor.WriteAsync(buffer, 0, buffer.Length);
                        }
                        Assert.Throws <InvalidOperationException>(() => { compressor.FlushAsync(); }); // "overlapping flushes"
                    }
                    finally
                    {
                        // Unblock Async operations
                        writeStream.manualResetEvent.Set();
                        // The original WriteAsync should be able to complete
                        Assert.True(task.Wait(TaskTimeout), "Original WriteAsync Task did not complete in time");
                        Assert.True(writeStream.WriteHit, "BaseStream Write function was not called");
                    }
                }
        }
        public async Task FlushAsync_DuringReadAsync()
        {
            byte[] buffer       = new byte[32];
            string testFilePath = CompressedTestFile(UncompressedTestFile());

            using (var readStream = await ManualSyncMemoryStream.GetStreamFromFileAsync(testFilePath, false))
                using (var decompressor = CreateStream(readStream, CompressionMode.Decompress, true))
                {
                    Task task = null;
                    try
                    {
                        readStream.manualResetEvent.Reset();
                        readStream.ReadHit = false;
                        task = decompressor.ReadAsync(buffer, 0, 32);
                        Assert.True(readStream.ReadHit);
                        Assert.Throws <InvalidOperationException>(() => { decompressor.FlushAsync(); }); // "overlapping read"
                    }
                    finally
                    {
                        // Unblock Async operations
                        readStream.manualResetEvent.Set();
                        // The original ReadAsync should be able to complete
                        Assert.True(task.Wait(TaskTimeout), "Original ReadAsync Task did not complete in time");
                    }
                }
        }
        public bool WriteHit = false; // methods of the underlying stream. This bool acts as a toggle to check that they're being used.

        public static async Task <ManualSyncMemoryStream> GetStreamFromFileAsync(string testFile, bool sync = false)
        {
            var baseStream = await StreamHelpers.CreateTempCopyStream(testFile);

            var ms = new ManualSyncMemoryStream(sync);
            await baseStream.CopyToAsync(ms);

            ms.Position = 0;
            return(ms);
        }
        public virtual async Task Dispose_WithUnfinishedReadAsync()
        {
            string compressedPath   = CompressedTestFile(UncompressedTestFile());
            int    uncompressedSize = (int)new FileInfo(UncompressedTestFile()).Length;

            byte[] uncompressedBytes = new byte[uncompressedSize];

            using (var readStream = await ManualSyncMemoryStream.GetStreamFromFileAsync(compressedPath, false))
            {
                var  decompressor = CreateStream(readStream, CompressionMode.Decompress, true);
                Task task         = decompressor.ReadAsync(uncompressedBytes, 0, uncompressedBytes.Length);
                decompressor.Dispose();
                readStream.manualResetEvent.Set();
                Assert.Throws <AggregateException>(() => task.Wait(TaskTimeout));
            }
        }
        public async Task FlushAsync_DuringFlushAsync()
        {
            byte[] buffer       = null;
            string testFilePath = CompressedTestFile(UncompressedTestFile());

            using (var origStream = await LocalMemoryStream.readAppFileAsync(testFilePath))
            {
                buffer = origStream.ToArray();
            }

            using (var writeStream = new ManualSyncMemoryStream(false))
                using (var zip = CreateStream(writeStream, CompressionMode.Compress))
                {
                    Task task = null;
                    try
                    {
                        writeStream.manualResetEvent.Set();
                        await zip.WriteAsync(buffer, 0, buffer.Length);

                        writeStream.manualResetEvent.Reset();
                        writeStream.WriteHit = false;
                        task = zip.FlushAsync();
                        while (!writeStream.WriteHit && task.IsCompleted)
                        {
                            zip.Write(buffer, 0, 1);
                            task = zip.FlushAsync();
                        }

                        Assert.Throws <InvalidOperationException>(() => { zip.FlushAsync(); }); // "overlapping flushes"
                    }
                    finally
                    {
                        // Unblock Async operations
                        writeStream.manualResetEvent.Set();
                        // The original WriteAsync should be able to complete
                        Assert.True(task.Wait(TaskTimeout), "Original write Task did not complete in time");
                        Assert.True(writeStream.WriteHit, "Underlying Writesync function was not called.");
                    }
                }
        }