Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit bb34d5a

Browse files
committed
Add more tests for FileStream
- 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.
1 parent f646fa6 commit bb34d5a

File tree

7 files changed

+540
-154
lines changed

7 files changed

+540
-154
lines changed

src/System.IO.FileSystem/tests/FileStream/Flush.Sharing.cs

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 122 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,156 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4-
using System;
5-
using System.IO;
64
using Xunit;
75

86
namespace System.IO.FileSystem.Tests
97
{
108
public partial class FileStream_Flush : FileSystemTest
119
{
12-
[Fact]
13-
public void FlushThrowsForDisposedStream()
10+
[Theory]
11+
[InlineData(null)]
12+
[InlineData(false)]
13+
[InlineData(true)]
14+
public void FlushThrowsForDisposedStream(bool? flushToDisk)
1415
{
1516
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
1617
{
1718
fs.Dispose();
18-
Assert.Throws<ObjectDisposedException>(() => fs.Flush());
19+
Assert.Throws<ObjectDisposedException>(() => Flush(fs, flushToDisk));
1920
}
2021
}
2122

22-
[Fact]
23-
public void BasicFlushFunctionality()
23+
[Theory]
24+
[InlineData(null)]
25+
[InlineData(false)]
26+
[InlineData(true)]
27+
public void BasicFlushFunctionality(bool? flushToDisk)
2428
{
2529
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
2630
{
2731
fs.WriteByte(0);
28-
fs.Flush();
32+
Flush(fs, flushToDisk);
33+
34+
fs.WriteByte(0xFF);
35+
Flush(fs, flushToDisk);
2936
}
3037
}
3138

32-
[Fact]
33-
public void FlushOnReadOnlyFileDoesNotThrow()
39+
[Theory]
40+
[InlineData(null)]
41+
[InlineData(false)]
42+
[InlineData(true)]
43+
public void FlushWhenNothingToFlush(bool? flushToDisk)
3444
{
35-
string fileName = GetTestFilePath();
36-
using (FileStream fs = new FileStream(fileName, FileMode.Create))
45+
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
3746
{
3847
fs.WriteByte(0);
48+
Flush(fs, flushToDisk);
49+
50+
Flush(fs, flushToDisk);
51+
Flush(fs, flushToDisk);
52+
Flush(fs, flushToDisk);
3953
}
54+
}
4055

41-
using (FileStream fs = new FileStream(fileName, FileMode.Open))
56+
[Theory]
57+
[InlineData(null)]
58+
[InlineData(false)]
59+
[InlineData(true)]
60+
public void FlushOnReadOnlyStreamDoesNotThrow(bool? flushToDisk)
61+
{
62+
string fileName = GetTestFilePath();
63+
File.WriteAllBytes(fileName, new byte[] { 0 });
64+
File.SetAttributes(fileName, FileAttributes.ReadOnly);
65+
try
66+
{
67+
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
68+
{
69+
Flush(fs, flushToDisk);
70+
}
71+
}
72+
finally
4273
{
74+
File.SetAttributes(fileName, FileAttributes.Normal);
75+
}
76+
}
77+
78+
[Theory]
79+
[InlineData(null)]
80+
[InlineData(false)]
81+
[InlineData(true)]
82+
public void FlushAfterReading(bool? flushToDisk)
83+
{
84+
string fileName = GetTestFilePath();
85+
File.WriteAllBytes(fileName, TestBuffer);
86+
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 2))
87+
{
88+
Assert.Equal(TestBuffer[0], fs.ReadByte());
89+
Flush(fs, flushToDisk);
90+
}
91+
}
92+
93+
[Theory]
94+
[InlineData(null)]
95+
[InlineData(false)]
96+
[InlineData(true)]
97+
public void FlushWriteWithOtherClient(bool? flushToDisk)
98+
{
99+
string fileName = GetTestFilePath();
100+
101+
// ensure that we'll be using a buffer larger than our test data
102+
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, TestBuffer.Length * 2))
103+
using (FileStream fsr = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
104+
{
105+
fs.Write(TestBuffer, 0, TestBuffer.Length);
106+
Assert.Equal(TestBuffer.Length, fs.Length);
107+
108+
// Make sure that we've actually buffered it, read handle won't see any changes
109+
Assert.Equal(0, fsr.Length);
110+
111+
// This should cause a write, after it completes the two handles should be in sync
112+
Flush(fs, flushToDisk);
113+
Assert.Equal(TestBuffer.Length, fsr.Length);
114+
115+
byte[] buffer = new byte[TestBuffer.Length];
116+
fsr.Read(buffer, 0, buffer.Length);
117+
Assert.Equal(TestBuffer, buffer);
118+
}
119+
}
120+
121+
[Fact]
122+
public void FlushCallsFlush_flushToDisk_False()
123+
{
124+
using (StoreFlushArgFileStream fs = new StoreFlushArgFileStream(GetTestFilePath(), FileMode.Create))
125+
{
126+
fs.Flush();
127+
Assert.True(fs.LastFlushArg.HasValue);
128+
Assert.False(fs.LastFlushArg.Value);
129+
}
130+
}
131+
132+
private static void Flush(FileStream fs, bool? flushArg)
133+
{
134+
if (!flushArg.HasValue)
43135
fs.Flush();
136+
else
137+
fs.Flush(flushArg.Value);
138+
}
139+
140+
private sealed class StoreFlushArgFileStream : FileStream
141+
{
142+
public StoreFlushArgFileStream(string path, FileMode mode) : base(path, mode)
143+
{
144+
}
145+
146+
public bool? LastFlushArg;
147+
148+
public override void Flush(bool flushToDisk)
149+
{
150+
LastFlushArg = flushToDisk;
151+
base.Flush(flushToDisk);
44152
}
45153
}
154+
46155
}
47156
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using Xunit;
7+
8+
namespace System.IO.FileSystem.Tests
9+
{
10+
public partial class FileStream_FlushAsync : FileSystemTest
11+
{
12+
[Fact]
13+
public async Task FlushAsyncThrowsForDisposedStream()
14+
{
15+
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
16+
{
17+
fs.Dispose();
18+
await Assert.ThrowsAsync<ObjectDisposedException>(() => fs.FlushAsync());
19+
}
20+
}
21+
22+
[Fact]
23+
public async Task BasicFlushAsyncFunctionality()
24+
{
25+
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
26+
{
27+
fs.WriteByte(0);
28+
await fs.FlushAsync();
29+
30+
fs.WriteByte(0xFF);
31+
await fs.FlushAsync();
32+
}
33+
}
34+
35+
[Fact]
36+
public async Task FlushAsyncWhenNothingToFlush()
37+
{
38+
using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create))
39+
{
40+
fs.WriteByte(0);
41+
await fs.FlushAsync();
42+
43+
await fs.FlushAsync();
44+
await fs.FlushAsync();
45+
await fs.FlushAsync();
46+
}
47+
}
48+
49+
[Fact]
50+
public async Task FlushAsyncOnReadOnlyFileDoesNotThrow()
51+
{
52+
string fileName = GetTestFilePath();
53+
File.WriteAllBytes(fileName, new byte[] { 0 });
54+
File.SetAttributes(fileName, FileAttributes.ReadOnly);
55+
try
56+
{
57+
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
58+
{
59+
await fs.FlushAsync();
60+
}
61+
}
62+
finally
63+
{
64+
File.SetAttributes(fileName, FileAttributes.Normal);
65+
}
66+
}
67+
68+
[Theory]
69+
[InlineData(null)]
70+
[InlineData(false)]
71+
[InlineData(true)]
72+
public async Task FlushAfterReading(bool? flushToDisk)
73+
{
74+
string fileName = GetTestFilePath();
75+
File.WriteAllBytes(fileName, TestBuffer);
76+
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 2))
77+
{
78+
Assert.Equal(TestBuffer[0], fs.ReadByte());
79+
await fs.FlushAsync();
80+
}
81+
}
82+
83+
[Fact]
84+
public async Task FlushAsyncWriteWithOtherClient()
85+
{
86+
string fileName = GetTestFilePath();
87+
88+
// ensure that we'll be using a buffer larger than our test data
89+
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, TestBuffer.Length * 2))
90+
using (FileStream fsr = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
91+
{
92+
fs.Write(TestBuffer, 0, TestBuffer.Length);
93+
Assert.Equal(TestBuffer.Length, fs.Length);
94+
95+
// Make sure that we've actually buffered it, read handle won't see any changes
96+
Assert.Equal(0, fsr.Length);
97+
98+
// This should cause a write, after it completes the two handles should be in sync
99+
await fs.FlushAsync();
100+
Assert.Equal(TestBuffer.Length, fsr.Length);
101+
102+
byte[] buffer = new byte[TestBuffer.Length];
103+
fsr.Read(buffer, 0, buffer.Length);
104+
Assert.Equal(TestBuffer, buffer);
105+
}
106+
}
107+
108+
[Fact]
109+
public void FlushAsyncWithCanceledToken()
110+
{
111+
using (FileStream fs = File.OpenWrite(GetTestFilePath()))
112+
{
113+
Assert.True(fs.FlushAsync(new CancellationToken(true)).IsCanceled);
114+
}
115+
}
116+
117+
}
118+
}

0 commit comments

Comments
 (0)