Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File.*AllText* optimizations #58167

Merged
merged 18 commits into from
Oct 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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