Skip to content

Commit

Permalink
File.*AllText* optimizations (#58167)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephen Toub <[email protected]>
Co-authored-by: David Cantú <[email protected]>
  • Loading branch information
3 people authored Oct 14, 2021
1 parent edf638f commit cf49643
Show file tree
Hide file tree
Showing 9 changed files with 425 additions and 420 deletions.
39 changes: 12 additions & 27 deletions src/libraries/System.IO.FileSystem/tests/File/Append.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,35 @@ namespace System.IO.Tests
{
public class File_AppendText : File_ReadWriteAllText
{
protected override bool IsAppend => true;

protected override void Write(string path, string content)
{
var writer = File.AppendText(path);
writer.Write(content);
writer.Dispose();
}

[Fact]
public override void Overwrite()
protected override void Write(string path, string content, Encoding encoding)
{
string path = GetTestFilePath();
string lines = new string('c', 200);
string appendLines = new string('b', 100);
Write(path, lines);
Write(path, appendLines);
Assert.Equal(lines + appendLines, Read(path));
var writer = new StreamWriter(path, IsAppend, encoding);
writer.Write(content);
writer.Dispose();
}
}

public class File_AppendAllText : File_ReadWriteAllText
{
protected override bool IsAppend => true;

protected override void Write(string path, string content)
{
File.AppendAllText(path, content);
}

[Fact]
public override void Overwrite()
protected override void Write(string path, string content, Encoding encoding)
{
string path = GetTestFilePath();
string lines = new string('c', 200);
string appendLines = new string('b', 100);
Write(path, lines);
Write(path, appendLines);
Assert.Equal(lines + appendLines, Read(path));
File.AppendAllText(path, content, encoding);
}
}

Expand All @@ -62,21 +56,12 @@ public void NullEncoding()

public class File_AppendAllLines : File_ReadWriteAllLines_Enumerable
{
protected override bool IsAppend => true;

protected override void Write(string path, string[] content)
{
File.AppendAllLines(path, content);
}

[Fact]
public override void Overwrite()
{
string path = GetTestFilePath();
string[] lines = new string[] { new string('c', 200) };
string[] appendLines = new string[] { new string('b', 100) };
Write(path, lines);
Write(path, appendLines);
Assert.Equal(new string[] { lines[0], appendLines[0] }, Read(path));
}
}

public class File_AppendAllLines_Encoded : File_AppendAllLines
Expand Down
26 changes: 5 additions & 21 deletions src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,11 @@ namespace System.IO.Tests
{
public class File_AppendAllTextAsync : File_ReadWriteAllTextAsync
{
protected override bool IsAppend => true;

protected override Task WriteAsync(string path, string content) => File.AppendAllTextAsync(path, content);

[Fact]
public override async Task OverwriteAsync()
{
string path = GetTestFilePath();
string lines = new string('c', 200);
string appendLines = new string('b', 100);
await WriteAsync(path, lines);
await WriteAsync(path, appendLines);
Assert.Equal(lines + appendLines, await ReadAsync(path));
}
protected override Task WriteAsync(string path, string content, Encoding encoding) => File.AppendAllTextAsync(path, content, encoding);

[Fact]
public override Task TaskAlreadyCanceledAsync()
Expand Down Expand Up @@ -60,18 +53,9 @@ public override Task TaskAlreadyCanceledAsync()

public class File_AppendAllLinesAsync : File_ReadWriteAllLines_EnumerableAsync
{
protected override Task WriteAsync(string path, string[] content) => File.AppendAllLinesAsync(path, content);
protected override bool IsAppend => true;

[Fact]
public override async Task OverwriteAsync()
{
string path = GetTestFilePath();
string[] lines = new string[] { new string('c', 200) };
string[] appendLines = new string[] { new string('b', 100) };
await WriteAsync(path, lines);
await WriteAsync(path, appendLines);
Assert.Equal(new string[] { lines[0], appendLines[0] }, await ReadAsync(path));
}
protected override Task WriteAsync(string path, string[] content) => File.AppendAllLinesAsync(path, content);

[Fact]
public override Task TaskAlreadyCanceledAsync()
Expand Down
25 changes: 20 additions & 5 deletions src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllLines.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class File_ReadWriteAllLines_Enumerable : FileSystemTest
{
#region Utilities

protected virtual bool IsAppend { get; }

protected virtual void Write(string path, string[] content)
{
File.WriteAllLines(path, (IEnumerable<string>)content);
Expand Down Expand Up @@ -66,15 +68,28 @@ public void ValidWrite(int size)
Assert.Equal(lines, Read(path));
}

[Fact]
public virtual void Overwrite()
[Theory]
[InlineData(200, 100)]
[InlineData(50_000, 40_000)] // tests a different code path than the line above
public void AppendOrOverwrite(int linesSizeLength, int overwriteLinesLength)
{
string path = GetTestFilePath();
string[] lines = new string[] { new string('c', 200) };
string[] overwriteLines = new string[] { new string('b', 100) };
string[] lines = new string[] { new string('c', linesSizeLength) };
string[] overwriteLines = new string[] { new string('b', overwriteLinesLength) };

Write(path, lines);
Write(path, overwriteLines);
Assert.Equal(overwriteLines, Read(path));

if (IsAppend)
{
Assert.Equal(new string[] { lines[0], overwriteLines[0] }, Read(path));
}
else
{
Assert.DoesNotContain("Append", GetType().Name); // ensure that all "Append" types override this property

Assert.Equal(overwriteLines, Read(path));
}
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public class File_ReadWriteAllLines_EnumerableAsync : FileSystemTest
{
#region Utilities

protected virtual bool IsAppend { get; }

protected virtual Task WriteAsync(string path, string[] content) =>
File.WriteAllLinesAsync(path, content);

Expand Down Expand Up @@ -64,15 +66,29 @@ public async Task ValidWriteAsync(int size)
Assert.Equal(lines, await ReadAsync(path));
}

[Fact]
public virtual async Task OverwriteAsync()

[Theory]
[InlineData(200, 100)]
[InlineData(50_000, 40_000)] // tests a different code path than the line above
public async Task AppendOrOverwrite(int linesSizeLength, int overwriteLinesLength)
{
string path = GetTestFilePath();
string[] lines = { new string('c', 200) };
string[] overwriteLines = { new string('b', 100) };
string[] lines = new string[] { new string('c', linesSizeLength) };
string[] overwriteLines = new string[] { new string('b', overwriteLinesLength) };

await WriteAsync(path, lines);
await WriteAsync(path, overwriteLines);
Assert.Equal(overwriteLines, await ReadAsync(path));

if (IsAppend)
{
Assert.Equal(new string[] { lines[0], overwriteLines[0] }, await ReadAsync(path));
}
else
{
Assert.DoesNotContain("Append", GetType().Name); // ensure that all "Append" types override this property

Assert.Equal(overwriteLines, await ReadAsync(path));
}
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))]
Expand Down
81 changes: 76 additions & 5 deletions src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllText.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Text;
using Xunit;

Expand All @@ -10,11 +11,18 @@ public class File_ReadWriteAllText : FileSystemTest
{
#region Utilities

protected virtual bool IsAppend { get; }

protected virtual void Write(string path, string content)
{
File.WriteAllText(path, content);
}

protected virtual void Write(string path, string content, Encoding encoding)
{
File.WriteAllText(path, content, encoding);
}

protected virtual string Read(string path)
{
return File.ReadAllText(path);
Expand Down Expand Up @@ -73,15 +81,28 @@ public void ValidWrite(int size)
Assert.Equal(toWrite, Read(path));
}

[Fact]
public virtual void Overwrite()
[Theory]
[InlineData(200, 100)]
[InlineData(50_000, 40_000)] // tests a different code path than the line above
public void AppendOrOverwrite(int linesSizeLength, int overwriteLinesLength)
{
string path = GetTestFilePath();
string lines = new string('c', 200);
string overwriteLines = new string('b', 100);
string lines = new string('c', linesSizeLength);
string overwriteLines = new string('b', overwriteLinesLength);

Write(path, lines);
Write(path, overwriteLines);
Assert.Equal(overwriteLines, Read(path));

if (IsAppend)
{
Assert.Equal(lines + overwriteLines, Read(path));
}
else
{
Assert.DoesNotContain("Append", GetType().Name); // ensure that all "Append" types override this property

Assert.Equal(overwriteLines, Read(path));
}
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))]
Expand Down Expand Up @@ -133,6 +154,56 @@ public void WriteToReadOnlyFile()
}
}

public static IEnumerable<object[]> OutputIsTheSameAsForStreamWriter_Args()
{
string longText = new string('z', 50_000);
foreach (Encoding encoding in new[] { Encoding.Unicode , new UTF8Encoding(encoderShouldEmitUTF8Identifier: true), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false) })
{
foreach (string text in new[] { null, string.Empty, " ", "shortText", longText })
{
yield return new object[] { text, encoding };
}
}
}

[Theory]
[MemberData(nameof(OutputIsTheSameAsForStreamWriter_Args))]
public void OutputIsTheSameAsForStreamWriter(string content, Encoding encoding)
{
string filePath = GetTestFilePath();
Write(filePath, content, encoding); // it uses System.IO.File APIs

string swPath = GetTestFilePath();
using (StreamWriter sw = new StreamWriter(swPath, IsAppend, encoding))
{
sw.Write(content);
}

Assert.Equal(File.ReadAllText(swPath, encoding), File.ReadAllText(filePath, encoding));
Assert.Equal(File.ReadAllBytes(swPath), File.ReadAllBytes(filePath)); // ensure Preamble was stored
}

[Theory]
[MemberData(nameof(OutputIsTheSameAsForStreamWriter_Args))]
public void OutputIsTheSameAsForStreamWriter_Overwrite(string content, Encoding encoding)
{
string filePath = GetTestFilePath();
string swPath = GetTestFilePath();

for (int i = 0; i < 2; i++)
{
Write(filePath, content, encoding); // it uses System.IO.File APIs

using (StreamWriter sw = new StreamWriter(swPath, IsAppend, encoding))
{
sw.Write(content);
}
}

Assert.Equal(File.ReadAllText(swPath, encoding), File.ReadAllText(filePath, encoding));
Assert.Equal(File.ReadAllBytes(swPath), File.ReadAllBytes(filePath)); // ensure Preamble was stored once
}

#endregion
}

Expand Down
Loading

0 comments on commit cf49643

Please sign in to comment.