Skip to content

Commit

Permalink
[browser][file system] Tests System.IO.FileSystem (#39768)
Browse files Browse the repository at this point in the history
* [browser][file system] Tests System.IO.FileSystem

* Remove FileSystem from test project exclusions.

* [browser][filesystem] Comment on skipped tests due to IO.Pipes not supported

* [browser][filesystem] Comment on skipped tests due to monitor not supported

* Address review comments

* Address review comments on how to handle monitor PNSE

* Update src/libraries/System.IO.FileSystem/tests/File/GetSetTimes.cs

Co-authored-by: Jan Kotas <jkotas@microsoft.com>

* Add ActiveIssue for browser platform

```
        [ActiveIssue("#39955", TestPlatforms.Browser)]
        public void NotFoundErrorIsExpected()
```

* Simplify test case with `PlatformDetection.IsSuperUser` as per review comment

* Remove unused variable from tests

* Browser platform volume does not limit each component of the path to a total of 255 characters.

- Remove the test `DirectoryWithComponentLongerThanMaxComponentAsPath_ThrowsException` for Browser platform.
- Add new test `DirectoryWithComponentLongerThanMaxComponentAsPath_BrowserDoesNotThrowsException` for Browser platform in case this check is added in the future.

* Fix windows tests

* Add ActiveIssue to test System.IO.Tests.DirectoryInfo_Name.CurrentDirectory

- System.IO.Tests.DirectoryInfo_Name.CurrentDirectory does not pass because it is using Path.GetFileName on the current directory of "/".
- See issue #39998 for more information

* Add active issue for tests that need to support file locking.

* Add active issue for tests that need to support file locking.

* Browser volume does not have a limit on segments

* Remove browser platform test

* Remove active issue for NotFoundErrorIsExpected

* Remove platform specific from SkippingHiddenFiles

* Fix enumeration test errors failing from `HiddenFilesAreReturned`.

- WebAssembly (BROWSER) has dirent d_type but is not identifying correctly but by returning UNKNOWN the managed code properly stats the file to detect if entry is directory or not.

* Fix enumeration test errors failing from `HiddenFilesAreReturned`.

- WebAssembly (BROWSER) has dirent d_type but is not identifying correctly but by returning UNKNOWN the managed code properly stats the file to detect if entry is directory or not.

* Fix build for TARGET_WASM not defined

* Address review comment by add check for IsWindows to IsSuperUser.

* Address review comment by add check for IsWindows to IsSuperUser.

* Platform Specific test for hidden files no longer needed.

* Platform Specific test fno longer needed.

* Use active issue for rename issue

* ActiveIssue no longer needed

- PR #40310 works around the issue for now while waiting for fix emscripten-core/emscripten#11804 / emscripten-core/emscripten#11812

* Use ActiveIssue for SettingUpdatesProperties

* Use ActiveIssue for TimesIncludeMillisecondPart

* Use ActiveIssue for ErrorHandlingTests failures

* Use ActiveIssue for SetUptoNanoseconds

* Use ActiveIssue for GetSetTimes test failures

* Use ActiveIssue for tests failing with DirectoryNotFoundException

* Use ActiveIssue for tests failing with UnauthorizedAccessException

* Remove debugging statement from pal_io

* Address type in CreateDirectory method name

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Mitchell Hwang <mitchell.hwang@microsoft.com>
  • Loading branch information
3 people authored Aug 10, 2020
1 parent a4eba0a commit 4dbe414
Show file tree
Hide file tree
Showing 35 changed files with 96 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ public static partial class PlatformDetection
public static bool IsNotFedoraOrRedHatFamily => !IsFedora && !IsRedHatFamily;
public static bool IsNotDebian10 => !IsDebian10;

public static bool IsSuperUser => IsBrowser ? false : (!IsWindows ?
libc.geteuid() == 0 :
throw new PlatformNotSupportedException());
public static bool IsSuperUser => IsBrowser || IsWindows ? false : libc.geteuid() == 0;

public static Version OpenSslVersion => !IsOSXLike && !IsWindows ?
GetOpenSslVersion() :
Expand Down
10 changes: 8 additions & 2 deletions src/libraries/Native/Unix/System.Native/pal_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ c_static_assert(PAL_S_IFSOCK == S_IFSOCK);
// Validate that our enum for inode types is the same as what is
// declared by the dirent.h header on the local system.
// (AIX doesn't have dirent d_type, so none of this there)
#if defined(DT_UNKNOWN)
// WebAssembly (BROWSER) has dirent d_type but is not correct
// by returning UNKNOWN the managed code properly stats the file
// to detect if entry is directory or not.
#if defined(DT_UNKNOWN) || defined(TARGET_WASM)
c_static_assert((int)PAL_DT_UNKNOWN == (int)DT_UNKNOWN);
c_static_assert((int)PAL_DT_FIFO == (int)DT_FIFO);
c_static_assert((int)PAL_DT_CHR == (int)DT_CHR);
Expand Down Expand Up @@ -345,10 +348,13 @@ static void ConvertDirent(const struct dirent* entry, DirectoryEntry* outputEntr
// the start of the unmanaged string. Give the caller back a pointer to the
// location of the start of the string that exists in their own byte buffer.
outputEntry->Name = entry->d_name;
#if !defined(DT_UNKNOWN)
#if !defined(DT_UNKNOWN) || defined(TARGET_WASM)
// AIX has no d_type, and since we can't get the directory that goes with
// the filename from ReadDir, we can't stat the file. Return unknown and
// hope that managed code can properly stat the file.
// WebAssembly (BROWSER) has dirent d_type but is not correct
// by returning UNKNOWN the managed code properly stats the file
// to detect if entry is directory or not.
outputEntry->InodeType = PAL_DT_UNKNOWN;
#else
outputEntry->InodeType = (int32_t)entry->d_type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public static TimeFunction Create(SetTime setter, GetTime getter, DateTimeKind k
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40528", TestPlatforms.Browser)]
public void SettingUpdatesProperties()
{
T item = GetExistingItem();
Expand Down Expand Up @@ -77,6 +78,7 @@ public void CanGetAllTimesAfterCreation()
}

[ConditionalFact(nameof(isNotHFS))] // OSX HFS driver format does not support millisec granularity
[ActiveIssue("https://github.com/dotnet/runtime/issues/40530", TestPlatforms.Browser)]
public void TimesIncludeMillisecondPart()
{
T item = GetExistingItem();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,17 +210,26 @@ public void DirectoryEqualToMaxDirectory_CanBeCreatedAllAtOnce()
Assert.Equal(path, result.FullName);
Assert.True(Directory.Exists(result.FullName));
}
#endregion

#region PlatformSpecific

[Theory,
MemberData(nameof(PathsWithComponentLongerThanMaxComponent))]
[PlatformSpecific(~TestPlatforms.Browser)] // Browser does not have a limit on the maximum component length
public void DirectoryWithComponentLongerThanMaxComponentAsPath_ThrowsException(string path)
{
AssertExtensions.ThrowsAny<IOException, DirectoryNotFoundException, PathTooLongException>(() => Create(path));
}

#endregion

#region PlatformSpecific
[Theory,
MemberData(nameof(PathsWithComponentLongerThanMaxComponent))]
[PlatformSpecific(TestPlatforms.Browser)] // Browser specific test in case the check changes in the future
public void DirectoryWithComponentLongerThanMaxComponentAsPath_BrowserDoesNotThrowException(string path)
{
DirectoryInfo result = Create(path);
Assert.True(Directory.Exists(path));
}

[Theory, MemberData(nameof(PathsWithInvalidColons))]
[PlatformSpecific(TestPlatforms.Windows)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ public void RecursiveDelete()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40536", TestPlatforms.Browser)]
public void RecursiveDeleteWithTrailingSlash()
{
DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ public void SubdirectoryOnNonExistentDriveAsPath_ReturnsFalse()
}

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)] // Makes call to native code (libc)
[PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] // Makes call to native code (libc)
public void FalseForNonRegularFile()
{
string fileName = GetTestFilePath();
Expand Down
1 change: 1 addition & 0 deletions src/libraries/System.IO.FileSystem/tests/Directory/Move.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ public void DirectoryNameWithSpaces()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40536", TestPlatforms.Browser)]
public void TrailingDirectorySeparators()
{
string testDirSource = Path.Combine(TestDirectory, GetTestFileName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void FalseForFile()
}

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)] // Uses P/Invokes
[PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] // Uses P/Invokes
public void FalseForNonRegularFile()
{
string fileName = GetTestFilePath();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ protected virtual void Move(DirectoryInfo sourceDir, string destDir)
#region UniversalTests

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40536", TestPlatforms.Browser)]
public void DirectoryPathUpdatesOnMove()
{
//NOTE: MoveTo adds a trailing separator character to the FullName of a DirectoryInfo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace System.IO.Tests
public class DirectoryInfo_Name : FileSystemTest
{
[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/39998", TestPlatforms.Browser)]
public void CurrentDirectory()
{
var info = new DirectoryInfo(".");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public void DeleteDirectoryAfterOpening()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40531", TestPlatforms.Browser)]
public void VariableLengthFileNames_AllCreatableFilesAreEnumerable()
{
DirectoryInfo testDirectory = Directory.CreateDirectory(GetTestFilePath());
Expand All @@ -119,6 +120,7 @@ public void VariableLengthFileNames_AllCreatableFilesAreEnumerable()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40531", TestPlatforms.Browser)]
public void VariableLengthDirectoryNames_AllCreatableDirectoriesAreEnumerable()
{
DirectoryInfo testDirectory = Directory.CreateDirectory(GetTestFilePath());
Expand Down
6 changes: 5 additions & 1 deletion src/libraries/System.IO.FileSystem/tests/File/Copy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public static IEnumerable<object[]> CopyFileWithData_MemberData()

[Theory]
[MemberData(nameof(CopyFileWithData_MemberData))]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40543", TestPlatforms.Browser)]
public void CopyFileWithData(char[] data, bool readOnly)
{
string testFileSource = GetTestFilePath();
Expand Down Expand Up @@ -140,7 +141,10 @@ public void CopyFileWithData(char[] data, bool readOnly)
}

// Ensure last write/access time on the new file is appropriate
Assert.InRange(File.GetLastWriteTimeUtc(testFileDest), lastWriteTime.AddSeconds(-1), lastWriteTime.AddSeconds(1));
if (PlatformDetection.IsNotBrowser) // There is only one write time on browser vfs
{
Assert.InRange(File.GetLastWriteTimeUtc(testFileDest), lastWriteTime.AddSeconds(-1), lastWriteTime.AddSeconds(1));
}

Assert.Equal(readOnly, (File.GetAttributes(testFileDest) & FileAttributes.ReadOnly) != 0);
if (readOnly)
Expand Down
10 changes: 6 additions & 4 deletions src/libraries/System.IO.FileSystem/tests/File/Create.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ public void InvalidDirectory()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40065", TestPlatforms.Browser)]
public void FileInUse()
{
DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());
Expand Down Expand Up @@ -144,7 +145,12 @@ public void OverwriteReadOnly()
Assert.True(File.Exists(testFile));
}

#endregion

#region PlatformSpecific

[Fact]
[PlatformSpecific(~TestPlatforms.Browser)] // Browser platform volume does not limit segments
public void LongPathSegment()
{
DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());
Expand All @@ -153,10 +159,6 @@ public void LongPathSegment()
Create(Path.Combine(testDir.FullName, new string('a', 300))));
}

#endregion

#region PlatformSpecific

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void LongDirectoryName()
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/System.IO.FileSystem/tests/File/Exists.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ public void DirectoryWithComponentLongerThanMaxComponentAsPath_ReturnsFalse(stri
}

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)] // Uses P/Invokes
[PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] // Uses P/Invokes
public void FalseForNonRegularFile()
{
string fileName = GetTestFilePath();
Expand Down
3 changes: 2 additions & 1 deletion src/libraries/System.IO.FileSystem/tests/File/GetSetTimes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class File_GetSetTimes : StaticGetSetTimes
{
// OSX has the limitation of setting upto 2262-04-11T23:47:16 (long.Max) date.
// 32bit Unix has time_t up to ~ 2038.
private static bool SupportsLongMaxDateTime => PlatformDetection.IsWindows || (RuntimeInformation.ProcessArchitecture != Architecture.Arm && RuntimeInformation.ProcessArchitecture != Architecture.X86 && !PlatformDetection.IsOSXLike);
private static bool SupportsLongMaxDateTime => PlatformDetection.IsWindows || (!PlatformDetection.Is32BitProcess && !PlatformDetection.IsOSXLike);

protected override string GetExistingItem()
{
Expand Down Expand Up @@ -135,6 +135,7 @@ public void SetLastWriteTimeTicks()
}

[ConditionalFact(nameof(isNotHFS))] // OSX HFS driver format does not support nanosecond granularity.
[ActiveIssue("https://github.com/dotnet/runtime/issues/40532", TestPlatforms.Browser)]
public void SetUptoNanoseconds()
{
string file = GetTestFilePath();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public void Overwrite()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40065", TestPlatforms.Browser)]
public void OpenFile_ThrowsIOException()
{
string path = GetTestFilePath();
Expand All @@ -105,7 +106,7 @@ public void WriteToReadOnlyFile()
try
{
// Operation succeeds when being run by the Unix superuser
if (!OperatingSystem.IsWindows() && geteuid() == 0)
if (PlatformDetection.IsSuperUser)
{
File.WriteAllBytes(path, Encoding.UTF8.GetBytes("text"));
Assert.Equal(Encoding.UTF8.GetBytes("text"), File.ReadAllBytes(path));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public async Task OverwriteAsync()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40065", TestPlatforms.Browser)]
public async Task OpenFile_ThrowsIOExceptionAsync()
{
string path = GetTestFilePath();
Expand All @@ -119,7 +120,7 @@ public async Task WriteToReadOnlyFileAsync()
try
{
// Operation succeeds when being run by the Unix superuser
if (!OperatingSystem.IsWindows() && geteuid() == 0)
if (PlatformDetection.IsSuperUser)
{
await File.WriteAllBytesAsync(path, Encoding.UTF8.GetBytes("text"));
Assert.Equal(Encoding.UTF8.GetBytes("text"), await File.ReadAllBytesAsync(path));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public virtual void Overwrite()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40065", TestPlatforms.Browser)]
public void OpenFile_ThrowsIOException()
{
string path = GetTestFilePath();
Expand Down Expand Up @@ -111,7 +112,7 @@ public void WriteToReadOnlyFile()
try
{
// Operation succeeds when being run by the Unix superuser
if (!OperatingSystem.IsWindows() && geteuid() == 0)
if (PlatformDetection.IsSuperUser)
{
Write(path, new string[] { "text" });
Assert.Equal(new string[] { "text" }, Read(path));
Expand Down Expand Up @@ -266,6 +267,7 @@ public virtual void Overwrite()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40065", TestPlatforms.Browser)]
public void OpenFile_ThrowsIOException()
{
string path = GetTestFilePath();
Expand Down Expand Up @@ -299,7 +301,7 @@ public void WriteToReadOnlyFile()
try
{
// Operation succeeds when being run by the Unix superuser
if (!OperatingSystem.IsWindows() && geteuid() == 0)
if (PlatformDetection.IsSuperUser)
{
Write(path, new string[] { "text" });
Assert.Equal(new string[] { "text" }, Read(path));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public virtual async Task OverwriteAsync()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40065", TestPlatforms.Browser)]
public async Task OpenFile_ThrowsIOExceptionAsync()
{
string path = GetTestFilePath();
Expand Down Expand Up @@ -106,7 +107,7 @@ public async Task WriteToReadOnlyFile()
try
{
// Operation succeeds when being run by the Unix superuser
if (!OperatingSystem.IsWindows() && geteuid() == 0)
if (PlatformDetection.IsSuperUser)
{
await WriteAsync(path, new string[] { "text" });
Assert.Equal(new string[] { "text" }, await ReadAsync(path));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public virtual void Overwrite()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40065", TestPlatforms.Browser)]
public void OpenFile_ThrowsIOException()
{
string path = GetTestFilePath();
Expand Down Expand Up @@ -118,7 +119,7 @@ public void WriteToReadOnlyFile()
try
{
// Operation succeeds when being run by the Unix superuser
if (!OperatingSystem.IsWindows() && geteuid() == 0)
if (PlatformDetection.IsSuperUser)
{
Write(path, "text");
Assert.Equal("text", Read(path));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public virtual async Task OverwriteAsync()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40065", TestPlatforms.Browser)]
public async Task OpenFile_ThrowsIOExceptionAsync()
{
string path = GetTestFilePath();
Expand Down Expand Up @@ -114,7 +115,7 @@ public async Task WriteToReadOnlyFileAsync()
try
{
// Operation succeeds when being run by the Unix superuser
if (!OperatingSystem.IsWindows() && geteuid() == 0)
if (PlatformDetection.IsSuperUser)
{
await WriteAsync(path, "text");
Assert.Equal("text", await ReadAsync(path));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public void FalseForDirectory()
}

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)] // Uses P/Invokes
[PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] // Uses P/Invokes
public void TrueForNonRegularFile()
{
string fileName = GetTestFilePath();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ public override IEnumerable<TimeFunction> TimeFunctions(bool requiresRoundtrippi
}

[ConditionalFact(nameof(isNotHFS))]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40530", TestPlatforms.Browser)]
public void CopyToMillisecondPresent()
{
FileInfo input = GetNonZeroMilliseconds();
Expand All @@ -118,6 +119,7 @@ public void CopyToMillisecondPresent()
}

[ConditionalFact(nameof(isNotHFS))]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40530", TestPlatforms.Browser)]
public void CopyToNanosecondsPresent()
{
FileInfo input = GetNonZeroNanoseconds();
Expand Down Expand Up @@ -160,6 +162,7 @@ public void MoveToMillisecondPresent_HFS()
}

[ConditionalFact(nameof(isNotHFS))]
[ActiveIssue("https://github.com/dotnet/runtime/issues/40530", TestPlatforms.Browser)]
public void MoveToMillisecondPresent()
{
FileInfo input = GetNonZeroMilliseconds();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public void CanSeekFalseForDisposedStream()
}

[Fact]
[PlatformSpecific(~TestPlatforms.Browser)] // IO.Pipes not supported
public void CanSeekReturnsFalseForPipe()
{
using (var pipeStream = new AnonymousPipeServerStream())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ public static IEnumerable<object[]> File_AllDataCopied_MemberData()

[Theory]
[InlineData(10, 1024)]
[PlatformSpecific(~TestPlatforms.Browser)] // IO.Pipes not supported
public async Task AnonymousPipeViaFileStream_AllDataCopied(int writeSize, int numWrites)
{
long totalLength = writeSize * numWrites;
Expand Down
Loading

0 comments on commit 4dbe414

Please sign in to comment.