From 46edbe424a71391a9130cf859cad70217aae7a0b Mon Sep 17 00:00:00 2001 From: Moji Date: Wed, 9 Aug 2023 08:24:29 +0200 Subject: [PATCH 01/28] Implement AppendAllBytes API --- .../System.Private.CoreLib/src/System/IO/File.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 84e8aa18df8a04..850fb555816a54 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -689,6 +689,22 @@ public static void WriteAllBytes(string path, byte[] bytes) RandomAccess.WriteAtOffset(sfh, bytes, 0); } + public static void AppendAllBytes(string path, byte[] bytes) + { + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(bytes); + + using SafeFileHandle fileHandle = OpenHandle(path, FileMode.Open, FileAccess.Write, FileShare.Read); + + if (fileHandle.CanSeek == false) + { + throw new NotSupportedException(); + } + + long fileOffset = RandomAccess.GetLength(fileHandle); + RandomAccess.WriteAtOffset(fileHandle, bytes, fileOffset); + } + public static string[] ReadAllLines(string path) => ReadAllLines(path, Encoding.UTF8); From 76a286867b1fe3973fa6f2119545943cf6ff01f1 Mon Sep 17 00:00:00 2001 From: Moji Date: Wed, 9 Aug 2023 08:29:08 +0200 Subject: [PATCH 02/28] Add AppendAllBytes declaration --- src/libraries/System.Runtime/ref/System.Runtime.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index a5963092303a51..f1e9b65fec20cf 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -9639,6 +9639,7 @@ public EnumerationOptions() { } } public static partial class File { + public static void AppendAllBytes(string path, byte[] bytes) { } public static void AppendAllLines(string path, System.Collections.Generic.IEnumerable contents) { } public static void AppendAllLines(string path, System.Collections.Generic.IEnumerable contents, System.Text.Encoding encoding) { } public static System.Threading.Tasks.Task AppendAllLinesAsync(string path, System.Collections.Generic.IEnumerable contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } From a8e8c8a73a6e61772b2efb175c40e5a93cdccb8f Mon Sep 17 00:00:00 2001 From: Moji Date: Wed, 9 Aug 2023 08:30:07 +0200 Subject: [PATCH 03/28] Add unit tests for AppendAllBytes --- .../System.IO.FileSystem/tests/File/Append.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/libraries/System.IO.FileSystem/tests/File/Append.cs b/src/libraries/System.IO.FileSystem/tests/File/Append.cs index 68160715a7d635..3f045efb3c8d0a 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/Append.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/Append.cs @@ -77,4 +77,23 @@ public void NullEncoding() Assert.Throws(() => File.AppendAllLines(GetTestFilePath(), new string[] { "Text" }, null)); } } + + public class File_AppendAllBytes: File_ReadWriteAllBytes + { + [Fact] + public void ValidParameters_ShouldAppendBytesToFile() + { + string path = GetTestFilePath(); + byte[] originalBytes = new byte[] { 1, 2, 3 }; + byte[] appendBytes = new byte[] { 4, 5, 6 }; + + File.WriteAllBytes(path, originalBytes); + File.AppendAllBytes(path, appendBytes); + + byte[] expectedBytes = new byte[] { 1, 2, 3, 4, 5, 6 }; + byte[] actualBytes = File.ReadAllBytes(path); + Assert.Equal(expectedBytes, actualBytes); + File.Delete(path); + } + } } From 454e9bc4733e3a60cf47f57ed4f591abae78a258 Mon Sep 17 00:00:00 2001 From: Moji Date: Thu, 10 Aug 2023 18:11:01 +0200 Subject: [PATCH 04/28] Add AppendAllBytesAsync tests --- .../tests/File/AppendAsync.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs index a4be5ccdd4e950..8da41b813b8da8 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs @@ -92,4 +92,34 @@ public override Task TaskAlreadyCanceledAsync() async () => await File.AppendAllLinesAsync(path, new[] { "" }, Encoding.UTF8, token)); } } + + public class File_AppendAllBytesAsync : File_ReadWriteAllBytesAsync + { + [Fact] + public async Task ValidParameters_ShouldAppendBytesToFileAsync() + { + string path = GetTestFilePath(); + byte[] originalBytes = new byte[] { 1, 2, 3 }; + byte[] appendBytes = new byte[] { 4, 5, 6 }; + + await File.WriteAllBytesAsync(path, originalBytes); + await File.AppendAllBytesAsync(path, appendBytes); + + byte[] expectedBytes = new byte[] { 1, 2, 3, 4, 5, 6 }; + byte[] actualBytes = await File.ReadAllBytesAsync(path); + Assert.Equal(expectedBytes, actualBytes); + File.Delete(path); + } + + [Fact] + public Task TaskAlreadyCanceledAsync() + { + string path = GetTestFilePath(); + var cancellationTokenSource = new CancellationTokenSource(); + cancellationTokenSource.Cancel(); + + return Assert.ThrowsAsync( + async () => await File.AppendAllBytesAsync(path, new byte[] { 1, 2, 3 }, cancellationTokenSource.Token)); + } + } } From 8719f0cfbb293d3642768c5508566aa45dc774e8 Mon Sep 17 00:00:00 2001 From: Moji Date: Thu, 10 Aug 2023 18:15:05 +0200 Subject: [PATCH 05/28] Add AppendAllBytesAsync implemntation --- .../src/System/IO/File.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 850fb555816a54..d0d051fd74ea13 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -705,6 +705,29 @@ public static void AppendAllBytes(string path, byte[] bytes) RandomAccess.WriteAtOffset(fileHandle, bytes, fileOffset); } + public static Task AppendAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken = default(CancellationToken)) + { + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(bytes); + + return cancellationToken.IsCancellationRequested + ? Task.FromCanceled(cancellationToken) + : Core(path, bytes, cancellationToken); + + static async Task Core(string path, byte[] bytes, CancellationToken cancellationToken) + { + using SafeFileHandle fileHandle = OpenHandle(path, FileMode.Open, FileAccess.Write, FileShare.Read, FileOptions.Asynchronous); + + if (fileHandle.CanSeek == false) + { + throw new NotSupportedException(); + } + + long fileOffset = RandomAccess.GetLength(fileHandle); + await RandomAccess.WriteAtOffsetAsync(fileHandle, bytes, fileOffset, cancellationToken).ConfigureAwait(false); + } + } + public static string[] ReadAllLines(string path) => ReadAllLines(path, Encoding.UTF8); From 9494297262bd4f0fcaa51f5fa57cf8ca3f0bd614 Mon Sep 17 00:00:00 2001 From: Moji Date: Thu, 10 Aug 2023 18:15:17 +0200 Subject: [PATCH 06/28] Add AppendAllBytesAsync definition --- src/libraries/System.Runtime/ref/System.Runtime.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index f1e9b65fec20cf..5863b443371dba 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -9640,6 +9640,7 @@ public EnumerationOptions() { } public static partial class File { public static void AppendAllBytes(string path, byte[] bytes) { } + public static System.Threading.Tasks.Task AppendAllBytesAsync(string path, byte[] bytes, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static void AppendAllLines(string path, System.Collections.Generic.IEnumerable contents) { } public static void AppendAllLines(string path, System.Collections.Generic.IEnumerable contents, System.Text.Encoding encoding) { } public static System.Threading.Tasks.Task AppendAllLinesAsync(string path, System.Collections.Generic.IEnumerable contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } From 9f4d03e5a51e3e8d1e7862af0f46767c5674ff79 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Fri, 11 Aug 2023 11:37:18 +0200 Subject: [PATCH 07/28] Removed unnecessary seek capability --- .../System.Private.CoreLib/src/System/IO/File.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index d0d051fd74ea13..9217653a053a36 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -695,12 +695,6 @@ public static void AppendAllBytes(string path, byte[] bytes) ArgumentNullException.ThrowIfNull(bytes); using SafeFileHandle fileHandle = OpenHandle(path, FileMode.Open, FileAccess.Write, FileShare.Read); - - if (fileHandle.CanSeek == false) - { - throw new NotSupportedException(); - } - long fileOffset = RandomAccess.GetLength(fileHandle); RandomAccess.WriteAtOffset(fileHandle, bytes, fileOffset); } @@ -717,12 +711,6 @@ public static void AppendAllBytes(string path, byte[] bytes) static async Task Core(string path, byte[] bytes, CancellationToken cancellationToken) { using SafeFileHandle fileHandle = OpenHandle(path, FileMode.Open, FileAccess.Write, FileShare.Read, FileOptions.Asynchronous); - - if (fileHandle.CanSeek == false) - { - throw new NotSupportedException(); - } - long fileOffset = RandomAccess.GetLength(fileHandle); await RandomAccess.WriteAtOffsetAsync(fileHandle, bytes, fileOffset, cancellationToken).ConfigureAwait(false); } From f34293a8078f076c47bf806a26adf906dc2ea872 Mon Sep 17 00:00:00 2001 From: Moji Date: Wed, 16 Aug 2023 18:45:52 +0200 Subject: [PATCH 08/28] Changed FileMode to Append to make it more readable and match the behavior --- src/libraries/System.Private.CoreLib/src/System/IO/File.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 9217653a053a36..a49e3502fd892b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -694,7 +694,7 @@ public static void AppendAllBytes(string path, byte[] bytes) ArgumentException.ThrowIfNullOrEmpty(path); ArgumentNullException.ThrowIfNull(bytes); - using SafeFileHandle fileHandle = OpenHandle(path, FileMode.Open, FileAccess.Write, FileShare.Read); + using SafeFileHandle fileHandle = OpenHandle(path, FileMode.Append, FileAccess.Write, FileShare.Read); long fileOffset = RandomAccess.GetLength(fileHandle); RandomAccess.WriteAtOffset(fileHandle, bytes, fileOffset); } @@ -710,7 +710,7 @@ public static void AppendAllBytes(string path, byte[] bytes) static async Task Core(string path, byte[] bytes, CancellationToken cancellationToken) { - using SafeFileHandle fileHandle = OpenHandle(path, FileMode.Open, FileAccess.Write, FileShare.Read, FileOptions.Asynchronous); + using SafeFileHandle fileHandle = OpenHandle(path, FileMode.Append, FileAccess.Write, FileShare.Read, FileOptions.Asynchronous); long fileOffset = RandomAccess.GetLength(fileHandle); await RandomAccess.WriteAtOffsetAsync(fileHandle, bytes, fileOffset, cancellationToken).ConfigureAwait(false); } From 547857acada5e932fda4291913f0ecc443222ec0 Mon Sep 17 00:00:00 2001 From: Moji Date: Sat, 14 Oct 2023 15:16:19 +0200 Subject: [PATCH 09/28] Move AppendAllBytes to separate class --- .../System.IO.FileSystem/tests/File/Append.cs | 19 --------- .../tests/File/AppendAllBytes.cs | 41 +++++++++++++++++++ .../tests/File/AppendAsync.cs | 30 -------------- .../tests/System.IO.FileSystem.Tests.csproj | 1 + 4 files changed, 42 insertions(+), 49 deletions(-) create mode 100644 src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs diff --git a/src/libraries/System.IO.FileSystem/tests/File/Append.cs b/src/libraries/System.IO.FileSystem/tests/File/Append.cs index 3f045efb3c8d0a..68160715a7d635 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/Append.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/Append.cs @@ -77,23 +77,4 @@ public void NullEncoding() Assert.Throws(() => File.AppendAllLines(GetTestFilePath(), new string[] { "Text" }, null)); } } - - public class File_AppendAllBytes: File_ReadWriteAllBytes - { - [Fact] - public void ValidParameters_ShouldAppendBytesToFile() - { - string path = GetTestFilePath(); - byte[] originalBytes = new byte[] { 1, 2, 3 }; - byte[] appendBytes = new byte[] { 4, 5, 6 }; - - File.WriteAllBytes(path, originalBytes); - File.AppendAllBytes(path, appendBytes); - - byte[] expectedBytes = new byte[] { 1, 2, 3, 4, 5, 6 }; - byte[] actualBytes = File.ReadAllBytes(path); - Assert.Equal(expectedBytes, actualBytes); - File.Delete(path); - } - } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs new file mode 100644 index 00000000000000..f3ecf7c87b677e --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO.Tests; +using System.Linq; +using System.Text; +using Xunit; + +namespace System.IO.Tests +{ + public class File_AppendAllBytes : FileSystemTest + { + + [Fact] + public void NullParameters() + { + string path = GetTestFilePath(); + + Assert.Throws(() => File.AppendAllBytes(null, new byte[] { 1, 2, 3 })); + Assert.Throws(() => File.AppendAllBytes(string.Empty, new byte[] { 1, 2, 3 })); + Assert.Throws(() => File.AppendAllBytes(path, null)); + } + + + [Fact] + public void AppendAllBytes_WithValidInput_AppendsBytes() + { + string path = GetTestFilePath(); + + byte[] initialBytes = new byte[] { 1, 2, 3 }; + byte[] additionalBytes = new byte[] { 4, 5, 6 }; + + File.WriteAllBytes(path, initialBytes); + File.AppendAllBytes(path, additionalBytes); + + byte[] result = File.ReadAllBytes(path); + + Assert.True(result.SequenceEqual(new byte[] { 1, 2, 3, 4, 5, 6 })); + } + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs index 8da41b813b8da8..a4be5ccdd4e950 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs @@ -92,34 +92,4 @@ public override Task TaskAlreadyCanceledAsync() async () => await File.AppendAllLinesAsync(path, new[] { "" }, Encoding.UTF8, token)); } } - - public class File_AppendAllBytesAsync : File_ReadWriteAllBytesAsync - { - [Fact] - public async Task ValidParameters_ShouldAppendBytesToFileAsync() - { - string path = GetTestFilePath(); - byte[] originalBytes = new byte[] { 1, 2, 3 }; - byte[] appendBytes = new byte[] { 4, 5, 6 }; - - await File.WriteAllBytesAsync(path, originalBytes); - await File.AppendAllBytesAsync(path, appendBytes); - - byte[] expectedBytes = new byte[] { 1, 2, 3, 4, 5, 6 }; - byte[] actualBytes = await File.ReadAllBytesAsync(path); - Assert.Equal(expectedBytes, actualBytes); - File.Delete(path); - } - - [Fact] - public Task TaskAlreadyCanceledAsync() - { - string path = GetTestFilePath(); - var cancellationTokenSource = new CancellationTokenSource(); - cancellationTokenSource.Cancel(); - - return Assert.ThrowsAsync( - async () => await File.AppendAllBytesAsync(path, new byte[] { 1, 2, 3 }, cancellationTokenSource.Token)); - } - } } diff --git a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj index 7547ddc53b2bb9..8a1667cbd8934d 100644 --- a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj +++ b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj @@ -35,6 +35,7 @@ + From 29ef4f2848943bd3349e7a87096b1457868dd4b7 Mon Sep 17 00:00:00 2001 From: Moji Date: Sat, 14 Oct 2023 16:15:17 +0200 Subject: [PATCH 10/28] Add extra tests to cover more scenarios --- .../tests/File/AppendAllBytes.cs | 73 +++++++++++++++++-- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs index f3ecf7c87b677e..eb32cbc83a8fbd 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs @@ -16,26 +16,89 @@ public void NullParameters() { string path = GetTestFilePath(); - Assert.Throws(() => File.AppendAllBytes(null, new byte[] { 1, 2, 3 })); - Assert.Throws(() => File.AppendAllBytes(string.Empty, new byte[] { 1, 2, 3 })); + Assert.Throws(() => File.AppendAllBytes(null, new byte[0])); Assert.Throws(() => File.AppendAllBytes(path, null)); } + [Fact] + public void InvalidParameters() + { + Assert.Throws(() => File.AppendAllBytes(string.Empty, new byte[0])); + } + [Fact] public void AppendAllBytes_WithValidInput_AppendsBytes() { string path = GetTestFilePath(); - byte[] initialBytes = new byte[] { 1, 2, 3 }; - byte[] additionalBytes = new byte[] { 4, 5, 6 }; + byte[] initialBytes = Encoding.UTF8.GetBytes("bytes"); + byte[] additionalBytes = Encoding.UTF8.GetBytes("additional bytes"); File.WriteAllBytes(path, initialBytes); File.AppendAllBytes(path, additionalBytes); byte[] result = File.ReadAllBytes(path); - Assert.True(result.SequenceEqual(new byte[] { 1, 2, 3, 4, 5, 6 })); + byte[] expectedBytes = initialBytes.Concat(additionalBytes).ToArray(); + + Assert.True(result.SequenceEqual(expectedBytes)); + } + + + [Fact] + public void EmptyContentCreatesFile() + { + string path = GetTestFilePath(); + File.AppendAllBytes(path, new byte[0]); + Assert.True(File.Exists(path)); + Assert.Empty(File.ReadAllBytes(path)); + File.Delete(path); } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))] + public void OpenFile_ThrowsIOException() + { + string path = GetTestFilePath(); + byte[] bytes = Encoding.UTF8.GetBytes("bytes"); + + using (File.Create(path)) + { + Assert.Throws(() => File.AppendAllBytes(path, bytes)); + Assert.Throws(() => File.ReadAllBytes(path)); + } + } + + /// + /// On Unix, modifying a file that is ReadOnly will fail under normal permissions. + /// If the test is being run under the superuser, however, modification of a ReadOnly + /// file is allowed. On Windows, modifying a file that is ReadOnly will always fail. + /// + [Fact] + public void AppendToReadOnlyFileAsync() + { + string path = GetTestFilePath(); + File.Create(path).Dispose(); + File.SetAttributes(path, FileAttributes.ReadOnly); + byte[] dataToAppend = Encoding.UTF8.GetBytes("bytes"); + + try + { + if (PlatformDetection.IsNotWindows && PlatformDetection.IsPrivilegedProcess) + { + File.AppendAllBytes(path, dataToAppend); + Assert.Equal(dataToAppend, File.ReadAllBytes(path)); + } + else + { + Assert.Throws(() => File.AppendAllBytes(path, dataToAppend)); + } + } + finally + { + File.SetAttributes(path, FileAttributes.Normal); + } + } + } } From b9a43de4e5492b4f6dd7d515bc12e94485d42371 Mon Sep 17 00:00:00 2001 From: Moji Date: Sat, 14 Oct 2023 16:18:47 +0200 Subject: [PATCH 11/28] Add tests to cover AppendAllBytesAsync --- .../tests/File/AppendAllBytesAsync.cs | 105 ++++++++++++++++++ .../tests/System.IO.FileSystem.Tests.csproj | 1 + 2 files changed, 106 insertions(+) create mode 100644 src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs new file mode 100644 index 00000000000000..4d32923ad569a5 --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs @@ -0,0 +1,105 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace System.IO.Tests +{ + public class File_AppendAllBytesAsync : FileSystemTest + { + + [Fact] + public async Task NullParametersAsync() + { + string path = GetTestFilePath(); + + await Assert.ThrowsAsync("path", async () => await File.AppendAllBytesAsync(null, new byte[0])); + await Assert.ThrowsAsync("bytes", async () => await File.AppendAllBytesAsync(path, null)); + } + + [Fact] + public async Task InvalidParametersAsync() + { + await Assert.ThrowsAsync("path", async () => await File.AppendAllBytesAsync(string.Empty, new byte[0])); + } + + [Fact] + public async Task AppendAllBytesAsync_WithValidInput_AppendsBytes() + { + string path = GetTestFilePath(); + + byte[] initialBytes = Encoding.UTF8.GetBytes("bytes"); + byte[] additionalBytes = Encoding.UTF8.GetBytes("additional bytes"); + + await File.WriteAllBytesAsync(path, initialBytes); + await File.AppendAllBytesAsync(path, additionalBytes); + + byte[] result = await File.ReadAllBytesAsync(path); + + byte[] expectedBytes = initialBytes.Concat(additionalBytes).ToArray(); + + Assert.True(result.SequenceEqual(expectedBytes)); + } + + [Fact] + public async Task EmptyContentCreatesFileAsync() + { + string path = GetTestFilePath(); + await File.AppendAllBytesAsync(path, new byte[0]); + Assert.True(File.Exists(path)); + Assert.Empty(await File.ReadAllBytesAsync(path)); + File.Delete(path); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))] + public async Task OpenFile_ThrowsIOExceptionAsync() + { + string path = GetTestFilePath(); + byte[] bytes = Encoding.UTF8.GetBytes("bytes"); + + using (File.Create(path)) + { + await Assert.ThrowsAsync(async () => await File.AppendAllBytesAsync(path, bytes)); + await Assert.ThrowsAsync(async () => await File.ReadAllBytesAsync(path)); + } + } + + /// + /// On Unix, modifying a file that is ReadOnly will fail under normal permissions. + /// If the test is being run under the superuser, however, modification of a ReadOnly + /// file is allowed. On Windows, modifying a file that is ReadOnly will always fail. + /// + [Fact] + public async Task AppendToReadOnlyFileAsync() + { + string path = GetTestFilePath(); + File.Create(path).Dispose(); + File.SetAttributes(path, FileAttributes.ReadOnly); + byte[] dataToAppend = Encoding.UTF8.GetBytes("bytes"); + + try + { + if (PlatformDetection.IsNotWindows && PlatformDetection.IsPrivilegedProcess) + { + await File.AppendAllBytesAsync(path, dataToAppend); + Assert.Equal(dataToAppend, await File.ReadAllBytesAsync(path)); + } + else + { + await Assert.ThrowsAsync(async () => await File.AppendAllBytesAsync(path, dataToAppend)); + } + } + finally + { + File.SetAttributes(path, FileAttributes.Normal); + } + } + + } + +} diff --git a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj index 8a1667cbd8934d..7e8ff6235add70 100644 --- a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj +++ b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj @@ -34,6 +34,7 @@ + From 8d91982b3555cdc88bae0b74b498040dba6a26a0 Mon Sep 17 00:00:00 2001 From: Moji Date: Sat, 14 Oct 2023 16:23:26 +0200 Subject: [PATCH 12/28] Remove unnecessary delete test file, becuase its removed by cleanup --- src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs | 1 - .../System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs index eb32cbc83a8fbd..0181160382f0ad 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs @@ -53,7 +53,6 @@ public void EmptyContentCreatesFile() File.AppendAllBytes(path, new byte[0]); Assert.True(File.Exists(path)); Assert.Empty(File.ReadAllBytes(path)); - File.Delete(path); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))] diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs index 4d32923ad569a5..a897bd5b54127a 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs @@ -53,7 +53,6 @@ public async Task EmptyContentCreatesFileAsync() await File.AppendAllBytesAsync(path, new byte[0]); Assert.True(File.Exists(path)); Assert.Empty(await File.ReadAllBytesAsync(path)); - File.Delete(path); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))] From 102f32825d4cc19593e8e3742225b8bc8a351a9c Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Tue, 17 Oct 2023 07:24:17 +0200 Subject: [PATCH 13/28] Add API documentation --- .../src/System/IO/File.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index a49e3502fd892b..01a3ee748a0a81 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -689,6 +689,20 @@ public static void WriteAllBytes(string path, byte[] bytes) RandomAccess.WriteAtOffset(sfh, bytes, 0); } + /// + /// Appends the specified byte array to the end of the file at the given path. + /// If the file doesn't exist, this method creates a new file. + /// + /// The path of the file to which the bytes should be appended. + /// The byte array to append to the file. + /// + /// Thrown when is a zero-length string, contains invalid characters + /// (which can be queried using the method), + /// or when is null or empty. + /// + /// + /// Thrown when is . + /// public static void AppendAllBytes(string path, byte[] bytes) { ArgumentException.ThrowIfNullOrEmpty(path); @@ -699,6 +713,22 @@ public static void AppendAllBytes(string path, byte[] bytes) RandomAccess.WriteAtOffset(fileHandle, bytes, fileOffset); } + /// + /// Asynchronously appends the specified byte array to the end of the file at the given path. + /// If the file doesn't exist, this method creates a new file. If the operation is canceled, the task will be returned in a canceled state. + /// + /// The path of the file to which the bytes should be appended. + /// The byte array to append to the file. + /// A token to monitor for cancellation requests. The default value is . + /// A task that represents the asynchronous append operation. + /// + /// Thrown when is a zero-length string, contains invalid characters + /// (which can be queried using the method), + /// or when is null or empty. + /// + /// + /// Thrown when is . + /// public static Task AppendAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken = default(CancellationToken)) { ArgumentException.ThrowIfNullOrEmpty(path); From f9ced06a74ac0d423b44af7cfe02c7449b1d9648 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 20:33:43 +0200 Subject: [PATCH 14/28] Remove extra space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Cantú --- src/libraries/System.Private.CoreLib/src/System/IO/File.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 01a3ee748a0a81..46433802102dda 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -690,7 +690,7 @@ public static void WriteAllBytes(string path, byte[] bytes) } /// - /// Appends the specified byte array to the end of the file at the given path. + /// Appends the specified byte array to the end of the file at the given path. /// If the file doesn't exist, this method creates a new file. /// /// The path of the file to which the bytes should be appended. From d84f25a7a5fac2339bdd048772d3ef3970db6059 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 20:34:23 +0200 Subject: [PATCH 15/28] Remove extra space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Cantú --- src/libraries/System.Private.CoreLib/src/System/IO/File.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 46433802102dda..1dcfaab8542231 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -696,7 +696,7 @@ public static void WriteAllBytes(string path, byte[] bytes) /// The path of the file to which the bytes should be appended. /// The byte array to append to the file. /// - /// Thrown when is a zero-length string, contains invalid characters + /// Thrown when is a zero-length string, contains invalid characters /// (which can be queried using the method), /// or when is null or empty. /// From db52294d8a48b51557af0bed6af70ef09fa7f476 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 20:34:46 +0200 Subject: [PATCH 16/28] update description of API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Cantú --- src/libraries/System.Private.CoreLib/src/System/IO/File.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 1dcfaab8542231..b765b569aa3fdb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -694,7 +694,7 @@ public static void WriteAllBytes(string path, byte[] bytes) /// If the file doesn't exist, this method creates a new file. /// /// The path of the file to which the bytes should be appended. - /// The byte array to append to the file. + /// The bytes to append to the file. /// /// Thrown when is a zero-length string, contains invalid characters /// (which can be queried using the method), From 8931cade37f3c2473bb4e09c4bd3cca9497d8323 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 20:35:28 +0200 Subject: [PATCH 17/28] Update param description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Cantú --- src/libraries/System.Private.CoreLib/src/System/IO/File.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index b765b569aa3fdb..ae13077de69585 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -693,7 +693,7 @@ public static void WriteAllBytes(string path, byte[] bytes) /// Appends the specified byte array to the end of the file at the given path. /// If the file doesn't exist, this method creates a new file. /// - /// The path of the file to which the bytes should be appended. + /// The file to append to. /// The bytes to append to the file. /// /// Thrown when is a zero-length string, contains invalid characters From ef54dfdb84ca7f8fe3849480931bfe0b8a0033f1 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 20:37:50 +0200 Subject: [PATCH 18/28] Remove extra space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Cantú --- src/libraries/System.Private.CoreLib/src/System/IO/File.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index ae13077de69585..6815b76dbb1505 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -722,7 +722,7 @@ public static void AppendAllBytes(string path, byte[] bytes) /// A token to monitor for cancellation requests. The default value is . /// A task that represents the asynchronous append operation. /// - /// Thrown when is a zero-length string, contains invalid characters + /// Thrown when is a zero-length string, contains invalid characters /// (which can be queried using the method), /// or when is null or empty. /// From 7d88c9b3635ed34ec93749db0d656992aab230c7 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 20:38:06 +0200 Subject: [PATCH 19/28] Remove extra space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Cantú --- src/libraries/System.Private.CoreLib/src/System/IO/File.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 6815b76dbb1505..9fa1edb6646584 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -723,7 +723,7 @@ public static void AppendAllBytes(string path, byte[] bytes) /// A task that represents the asynchronous append operation. /// /// Thrown when is a zero-length string, contains invalid characters - /// (which can be queried using the method), + /// (which can be queried using the method), /// or when is null or empty. /// /// From 6baf0f65cafb836764ccbfd69655ed9282739a0d Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 20:39:14 +0200 Subject: [PATCH 20/28] Remove unnecessary test scenario MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Cantú --- src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs index 0181160382f0ad..f964e9e8fc6073 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs @@ -64,7 +64,6 @@ public void OpenFile_ThrowsIOException() using (File.Create(path)) { Assert.Throws(() => File.AppendAllBytes(path, bytes)); - Assert.Throws(() => File.ReadAllBytes(path)); } } From ca70a5c9cbedeabf7c7bf10b31aac28b96792f6b Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 20:39:36 +0200 Subject: [PATCH 21/28] Remove unnecessary test scenario MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Cantú --- .../System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs index a897bd5b54127a..b026fe4fc4354a 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs @@ -64,7 +64,6 @@ public async Task OpenFile_ThrowsIOExceptionAsync() using (File.Create(path)) { await Assert.ThrowsAsync(async () => await File.AppendAllBytesAsync(path, bytes)); - await Assert.ThrowsAsync(async () => await File.ReadAllBytesAsync(path)); } } From 0618e7d3add25426e76ff18eac101d2d91a059d3 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 20:39:56 +0200 Subject: [PATCH 22/28] Remove extra space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Cantú --- src/libraries/System.Private.CoreLib/src/System/IO/File.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 9fa1edb6646584..d63eb372bf3dbc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -714,7 +714,7 @@ public static void AppendAllBytes(string path, byte[] bytes) } /// - /// Asynchronously appends the specified byte array to the end of the file at the given path. + /// Asynchronously appends the specified byte array to the end of the file at the given path. /// If the file doesn't exist, this method creates a new file. If the operation is canceled, the task will be returned in a canceled state. /// /// The path of the file to which the bytes should be appended. From c3277fd2cf1b7f22d4b9c66745386ead36fed57e Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 20:56:48 +0200 Subject: [PATCH 23/28] Fix docusmentation of API --- .../System.Private.CoreLib/src/System/IO/File.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index d63eb372bf3dbc..71789d2888fca1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -695,13 +695,12 @@ public static void WriteAllBytes(string path, byte[] bytes) /// /// The file to append to. /// The bytes to append to the file. - /// - /// Thrown when is a zero-length string, contains invalid characters - /// (which can be queried using the method), - /// or when is null or empty. + /// + /// Thrown when is a zero-length string, contains only white space, + /// or contains invalid characters as defined by . /// - /// - /// Thrown when is . + /// + /// Thrown when is null, or when is null. /// public static void AppendAllBytes(string path, byte[] bytes) { From 11ec838e069bd05a1e6dc39ee8a4f4477f896f92 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 21:32:12 +0200 Subject: [PATCH 24/28] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove unwanted spaces in files - Fix API documentation - Add assertation for file exists Co-authored-by: David Cantú --- .../tests/File/AppendAllBytes.cs | 2 +- .../tests/File/AppendAllBytesAsync.cs | 2 -- .../src/System/IO/File.cs | 18 +++++++++--------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs index f964e9e8fc6073..397314ac503d12 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs @@ -50,6 +50,7 @@ public void AppendAllBytes_WithValidInput_AppendsBytes() public void EmptyContentCreatesFile() { string path = GetTestFilePath(); + Assert.False(File.Exists(path)); File.AppendAllBytes(path, new byte[0]); Assert.True(File.Exists(path)); Assert.Empty(File.ReadAllBytes(path)); @@ -97,6 +98,5 @@ public void AppendToReadOnlyFileAsync() File.SetAttributes(path, FileAttributes.Normal); } } - } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs index b026fe4fc4354a..d0ae8fb50104ad 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs @@ -97,7 +97,5 @@ public async Task AppendToReadOnlyFileAsync() File.SetAttributes(path, FileAttributes.Normal); } } - } - } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 71789d2888fca1..327c315ab90c82 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -696,11 +696,10 @@ public static void WriteAllBytes(string path, byte[] bytes) /// The file to append to. /// The bytes to append to the file. /// - /// Thrown when is a zero-length string, contains only white space, - /// or contains invalid characters as defined by . + /// is a zero-length string, contains only white space, or contains one more invalid characters defined by the method. /// /// - /// Thrown when is null, or when is null. + /// Either or is null. /// public static void AppendAllBytes(string path, byte[] bytes) { @@ -716,17 +715,18 @@ public static void AppendAllBytes(string path, byte[] bytes) /// Asynchronously appends the specified byte array to the end of the file at the given path. /// If the file doesn't exist, this method creates a new file. If the operation is canceled, the task will be returned in a canceled state. /// - /// The path of the file to which the bytes should be appended. + /// The file to append to. /// The byte array to append to the file. - /// A token to monitor for cancellation requests. The default value is . + /// The token to monitor for cancellation requests. The default value is . /// A task that represents the asynchronous append operation. /// - /// Thrown when is a zero-length string, contains invalid characters - /// (which can be queried using the method), - /// or when is null or empty. + /// is a zero-length string, contains only white space, or contains one more invalid characters defined by the method. /// /// - /// Thrown when is . + /// Either or is null. + /// + /// + /// The cancellation token was canceled. This exception is stored into the returned task. /// public static Task AppendAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken = default(CancellationToken)) { From 4eca48708743bb20a47dcbd32b51d38819f54ad0 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 22:38:53 +0200 Subject: [PATCH 25/28] Add test for scenario when directory not exists --- .../System.IO.FileSystem/tests/File/AppendAllBytes.cs | 6 ++++++ .../System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs index 397314ac503d12..9b29f971e20dfa 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytes.cs @@ -20,6 +20,12 @@ public void NullParameters() Assert.Throws(() => File.AppendAllBytes(path, null)); } + [Fact] + public void NonExistentPath() + { + Assert.Throws(() => File.AppendAllBytes(Path.Combine(TestDirectory, GetTestFileName(), GetTestFileName()), new byte[0])); + } + [Fact] public void InvalidParameters() { diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs index d0ae8fb50104ad..84ef880f4aa93f 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAllBytesAsync.cs @@ -22,6 +22,12 @@ public async Task NullParametersAsync() await Assert.ThrowsAsync("bytes", async () => await File.AppendAllBytesAsync(path, null)); } + [Fact] + public void NonExistentPathAsync() + { + Assert.ThrowsAsync(() => File.AppendAllBytesAsync(Path.Combine(TestDirectory, GetTestFileName(), GetTestFileName()), new byte[0])); + } + [Fact] public async Task InvalidParametersAsync() { From 73ad2218ac1ff5ae6a8cb678fb0c33b81833f363 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Mon, 23 Oct 2023 22:39:25 +0200 Subject: [PATCH 26/28] Fix Async documentation and match it with none-async version --- .../src/System/IO/File.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 327c315ab90c82..7458a865028d7d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -713,20 +713,18 @@ public static void AppendAllBytes(string path, byte[] bytes) /// /// Asynchronously appends the specified byte array to the end of the file at the given path. - /// If the file doesn't exist, this method creates a new file. If the operation is canceled, the task will be returned in a canceled state. + /// If the file does not exist, a new file will be created. If the operation is canceled, the task will return in a canceled state. /// /// The file to append to. - /// The byte array to append to the file. - /// The token to monitor for cancellation requests. The default value is . + /// The bytes to append to the file. + /// A token to monitor for cancellation requests. The default value is . /// A task that represents the asynchronous append operation. - /// - /// is a zero-length string, contains only white space, or contains one more invalid characters defined by the method. - /// - /// - /// Either or is null. + /// + /// Thrown when is a zero-length string, contains only white space, + /// or contains invalid characters as defined by . /// - /// - /// The cancellation token was canceled. This exception is stored into the returned task. + /// + /// Thrown when is null, or when is null. /// public static Task AppendAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken = default(CancellationToken)) { From 9988eb8f430dc909c9b5ca626390feea7b6c361a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Mon, 23 Oct 2023 17:28:39 -0500 Subject: [PATCH 27/28] Apply suggestions from code review --- .../System.Private.CoreLib/src/System/IO/File.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 7458a865028d7d..58ac636b4b68fe 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -713,19 +713,21 @@ public static void AppendAllBytes(string path, byte[] bytes) /// /// Asynchronously appends the specified byte array to the end of the file at the given path. - /// If the file does not exist, a new file will be created. If the operation is canceled, the task will return in a canceled state. + /// If the file doesn't exist, this method creates a new file. If the operation is canceled, the task will return in a canceled state. /// /// The file to append to. /// The bytes to append to the file. - /// A token to monitor for cancellation requests. The default value is . + /// The token to monitor for cancellation requests. The default value is . /// A task that represents the asynchronous append operation. /// - /// Thrown when is a zero-length string, contains only white space, - /// or contains invalid characters as defined by . + /// is a zero-length string, contains only white space, or contains one more invalid characters defined by the method. /// /// - /// Thrown when is null, or when is null. + /// Either or is null. /// + /// + /// The cancellation token was canceled. This exception is stored into the returned task. + /// public static Task AppendAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken = default(CancellationToken)) { ArgumentException.ThrowIfNullOrEmpty(path); From 647a914cdd2873787af6067511149222d9dd5cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Mon, 23 Oct 2023 17:45:39 -0500 Subject: [PATCH 28/28] Change tabs for spaces --- src/libraries/System.Private.CoreLib/src/System/IO/File.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 58ac636b4b68fe..ec17866f079217 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -726,8 +726,8 @@ public static void AppendAllBytes(string path, byte[] bytes) /// Either or is null. /// /// - /// The cancellation token was canceled. This exception is stored into the returned task. - /// + /// The cancellation token was canceled. This exception is stored into the returned task. + /// public static Task AppendAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken = default(CancellationToken)) { ArgumentException.ThrowIfNullOrEmpty(path);