Skip to content

Commit

Permalink
Add more tests for FileStream
Browse files Browse the repository at this point in the history
- Mainly, I added several tests (with lots of theory-based parameterized inputs) to stress WriteAsync: many concurrent writes, long chains of writes, etc., for various size inputs and buffers, async vs not, etc.
- There were multiple variations on Flush tests based on whether to use Flush(), Flush(false), or False(true).  I combined these all into single theories.
- I then added some more Flush tests for some missing cases highlighted by code coverage, e.g. flushing reads.
- I then duplicated these tests for FlushAsync, and added some additional tests specific to FlushAsync, e.g. cancellation.
- I added a few tests for pipes.


Commit migrated from dotnet/corefx@bb34d5a
  • Loading branch information
stephentoub committed Aug 24, 2015
1 parent 550a223 commit 26253f6
Show file tree
Hide file tree
Showing 7 changed files with 540 additions and 154 deletions.

This file was deleted.

135 changes: 122 additions & 13 deletions src/libraries/System.IO.FileSystem/tests/FileStream/Flush.cs
Original file line number Diff line number Diff line change
@@ -1,47 +1,156 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.IO;
using Xunit;

namespace System.IO.FileSystem.Tests
{
public partial class FileStream_Flush : FileSystemTest
{
[Fact]
public void FlushThrowsForDisposedStream()
[Theory]
[InlineData(null)]
[InlineData(false)]
[InlineData(true)]
public void FlushThrowsForDisposedStream(bool? flushToDisk)
{
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
{
fs.Dispose();
Assert.Throws<ObjectDisposedException>(() => fs.Flush());
Assert.Throws<ObjectDisposedException>(() => Flush(fs, flushToDisk));
}
}

[Fact]
public void BasicFlushFunctionality()
[Theory]
[InlineData(null)]
[InlineData(false)]
[InlineData(true)]
public void BasicFlushFunctionality(bool? flushToDisk)
{
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
{
fs.WriteByte(0);
fs.Flush();
Flush(fs, flushToDisk);

fs.WriteByte(0xFF);
Flush(fs, flushToDisk);
}
}

[Fact]
public void FlushOnReadOnlyFileDoesNotThrow()
[Theory]
[InlineData(null)]
[InlineData(false)]
[InlineData(true)]
public void FlushWhenNothingToFlush(bool? flushToDisk)
{
string fileName = GetTestFilePath();
using (FileStream fs = new FileStream(fileName, FileMode.Create))
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
{
fs.WriteByte(0);
Flush(fs, flushToDisk);

Flush(fs, flushToDisk);
Flush(fs, flushToDisk);
Flush(fs, flushToDisk);
}
}

using (FileStream fs = new FileStream(fileName, FileMode.Open))
[Theory]
[InlineData(null)]
[InlineData(false)]
[InlineData(true)]
public void FlushOnReadOnlyStreamDoesNotThrow(bool? flushToDisk)
{
string fileName = GetTestFilePath();
File.WriteAllBytes(fileName, new byte[] { 0 });
File.SetAttributes(fileName, FileAttributes.ReadOnly);
try
{
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
Flush(fs, flushToDisk);
}
}
finally
{
File.SetAttributes(fileName, FileAttributes.Normal);
}
}

[Theory]
[InlineData(null)]
[InlineData(false)]
[InlineData(true)]
public void FlushAfterReading(bool? flushToDisk)
{
string fileName = GetTestFilePath();
File.WriteAllBytes(fileName, TestBuffer);
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 2))
{
Assert.Equal(TestBuffer[0], fs.ReadByte());
Flush(fs, flushToDisk);
}
}

[Theory]
[InlineData(null)]
[InlineData(false)]
[InlineData(true)]
public void FlushWriteWithOtherClient(bool? flushToDisk)
{
string fileName = GetTestFilePath();

// ensure that we'll be using a buffer larger than our test data
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, TestBuffer.Length * 2))
using (FileStream fsr = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
fs.Write(TestBuffer, 0, TestBuffer.Length);
Assert.Equal(TestBuffer.Length, fs.Length);

// Make sure that we've actually buffered it, read handle won't see any changes
Assert.Equal(0, fsr.Length);

// This should cause a write, after it completes the two handles should be in sync
Flush(fs, flushToDisk);
Assert.Equal(TestBuffer.Length, fsr.Length);

byte[] buffer = new byte[TestBuffer.Length];
fsr.Read(buffer, 0, buffer.Length);
Assert.Equal(TestBuffer, buffer);
}
}

[Fact]
public void FlushCallsFlush_flushToDisk_False()
{
using (StoreFlushArgFileStream fs = new StoreFlushArgFileStream(GetTestFilePath(), FileMode.Create))
{
fs.Flush();
Assert.True(fs.LastFlushArg.HasValue);
Assert.False(fs.LastFlushArg.Value);
}
}

private static void Flush(FileStream fs, bool? flushArg)
{
if (!flushArg.HasValue)
fs.Flush();
else
fs.Flush(flushArg.Value);
}

private sealed class StoreFlushArgFileStream : FileStream
{
public StoreFlushArgFileStream(string path, FileMode mode) : base(path, mode)
{
}

public bool? LastFlushArg;

public override void Flush(bool flushToDisk)
{
LastFlushArg = flushToDisk;
base.Flush(flushToDisk);
}
}

}
}
118 changes: 118 additions & 0 deletions src/libraries/System.IO.FileSystem/tests/FileStream/FlushAsync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Threading;
using System.Threading.Tasks;
using Xunit;

namespace System.IO.FileSystem.Tests
{
public partial class FileStream_FlushAsync : FileSystemTest
{
[Fact]
public async Task FlushAsyncThrowsForDisposedStream()
{
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
{
fs.Dispose();
await Assert.ThrowsAsync<ObjectDisposedException>(() => fs.FlushAsync());
}
}

[Fact]
public async Task BasicFlushAsyncFunctionality()
{
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
{
fs.WriteByte(0);
await fs.FlushAsync();

fs.WriteByte(0xFF);
await fs.FlushAsync();
}
}

[Fact]
public async Task FlushAsyncWhenNothingToFlush()
{
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
{
fs.WriteByte(0);
await fs.FlushAsync();

await fs.FlushAsync();
await fs.FlushAsync();
await fs.FlushAsync();
}
}

[Fact]
public async Task FlushAsyncOnReadOnlyFileDoesNotThrow()
{
string fileName = GetTestFilePath();
File.WriteAllBytes(fileName, new byte[] { 0 });
File.SetAttributes(fileName, FileAttributes.ReadOnly);
try
{
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
await fs.FlushAsync();
}
}
finally
{
File.SetAttributes(fileName, FileAttributes.Normal);
}
}

[Theory]
[InlineData(null)]
[InlineData(false)]
[InlineData(true)]
public async Task FlushAfterReading(bool? flushToDisk)
{
string fileName = GetTestFilePath();
File.WriteAllBytes(fileName, TestBuffer);
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 2))
{
Assert.Equal(TestBuffer[0], fs.ReadByte());
await fs.FlushAsync();
}
}

[Fact]
public async Task FlushAsyncWriteWithOtherClient()
{
string fileName = GetTestFilePath();

// ensure that we'll be using a buffer larger than our test data
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, TestBuffer.Length * 2))
using (FileStream fsr = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
fs.Write(TestBuffer, 0, TestBuffer.Length);
Assert.Equal(TestBuffer.Length, fs.Length);

// Make sure that we've actually buffered it, read handle won't see any changes
Assert.Equal(0, fsr.Length);

// This should cause a write, after it completes the two handles should be in sync
await fs.FlushAsync();
Assert.Equal(TestBuffer.Length, fsr.Length);

byte[] buffer = new byte[TestBuffer.Length];
fsr.Read(buffer, 0, buffer.Length);
Assert.Equal(TestBuffer, buffer);
}
}

[Fact]
public void FlushAsyncWithCanceledToken()
{
using (FileStream fs = File.OpenWrite(GetTestFilePath()))
{
Assert.True(fs.FlushAsync(new CancellationToken(true)).IsCanceled);
}
}

}
}
Loading

0 comments on commit 26253f6

Please sign in to comment.