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

[wasm] Addressing System.Runtime.Extensions failures #38996

Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
35a79fc
[wasm] Reenable some skipped tests in System.Runtime.Extensions.Tests
Jul 8, 2020
5c905bf
[wasm] PathTests GetFullPath_CoreTests skip test case on browser
Jul 8, 2020
cad48bb
[wasm] System.Runtime.Extensions Tests throwing PNSE
Jul 9, 2020
f8b3c60
[wasm] System.Runtime.Extensions tests throwing Cannot wait on monito…
Jul 9, 2020
9e41643
[wasm] System.Runtime.Extensions tests with ActiveIssues
Jul 9, 2020
0558735
[wasm] System.Runtime.Extensions test throwing EntryPointNotFoundExce…
Jul 9, 2020
c05deb2
[wasm] AppDomainTests modify expected FriendlyName
Jul 9, 2020
b19d161
Add Environment.Browser to eliminate p-invokes that were not function…
Jul 10, 2020
f1a5975
Adjust ICU dependent tests
Jul 10, 2020
c128f6d
Remove browser skip on WorkingSet_Valid
Jul 10, 2020
9745d57
Feedback
Jul 10, 2020
ff310ff
Feedback PathTests.cs
Jul 10, 2020
4a223ed
[wasm] EnvironmentTests Assert Environment.Workinset equals 0
Jul 10, 2020
1038c09
[wasm] StringComparer Use IsNotInvariantGlobalization instead of IsIc…
Jul 10, 2020
bf0521e
Remove System.Runtime.Extensions from skip test list
Jul 10, 2020
b937af6
[wasm] Return emscripten for GetComputerName on Browser
Jul 10, 2020
53350a0
Add back in Environment.UnixOrBrowser
Jul 10, 2020
f625e66
Cleaned up a few comments
Jul 10, 2020
3a4ea9c
Merge branch 'master' into mdhwang/address_system_runtime_extensions_…
akoeplinger Jul 11, 2020
8d13b06
Merge branch 'master' into mdhwang/address_system_runtime_extensions_…
akoeplinger Jul 11, 2020
952997c
PR Feedback
Jul 12, 2020
c7343fa
One more thing...
Jul 13, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -1790,7 +1790,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Stopwatch.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\RuntimeEventSourceHelper.Unix.cs" Condition="'$(FeaturePerfTracing)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.NoRegistry.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.UnixOrBrowser.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.OSVersion.OSX.cs" Condition="'$(IsOSXLike)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.OSVersion.Unix.cs" Condition="'$(IsOSXLike)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.GetFolderPathCore.Unix.cs" Condition="'$(TargetsiOS)' != 'true' and '$(TargetstvOS)' != 'true'" />
Expand Down Expand Up @@ -1818,6 +1818,12 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\TimerQueue.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.Unix.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsUnix)' == 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.Unix.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsBrowser)' == 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.Browser.cs" />
</ItemGroup>
<ItemGroup Condition="'$(IsOSXLike)' == 'true'">
<Compile Include="$(CommonPath)Interop\OSX\Interop.libobjc.cs">
<Link>Common\Interop\OSX\Interop.libobjc.cs</Link>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System
{
public static partial class Environment
{
// Emscripten VFS mounts at / and is the only drive
public static string[] GetLogicalDrives() => new string[] { "/" };

// In the mono runtime, this maps to gethostname, which returns 'emscripten'.
// Returning the value here allows us to exclude more of the runtime.
public static string MachineName => "emscripten";
steveisok marked this conversation as resolved.
Show resolved Hide resolved

// Matching what we returned for an earlier release. There isn't an established equivalent
// on wasm.
public static long WorkingSet => 0;

// Matching what we returned for an earlier release
public static string UserName => "web_user";
steveisok marked this conversation as resolved.
Show resolved Hide resolved
}
}
130 changes: 17 additions & 113 deletions src/libraries/System.Private.CoreLib/src/System/Environment.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,8 @@ namespace System
{
public static partial class Environment
{
public static bool UserInteractive => true;

private static string CurrentDirectoryCore
{
get => Interop.Sys.GetCwd();
set => Interop.CheckIo(Interop.Sys.ChDir(value), value, isDirectory: true);
}

private static string ExpandEnvironmentVariablesCore(string name)
{
var result = new ValueStringBuilder(stackalloc char[128]);

int lastPos = 0, pos;
while (lastPos < name.Length && (pos = name.IndexOf('%', lastPos + 1)) >= 0)
{
if (name[lastPos] == '%')
{
string key = name.Substring(lastPos + 1, pos - lastPos - 1);
string? value = GetEnvironmentVariable(key);
if (value != null)
{
result.Append(value);
lastPos = pos + 1;
continue;
}
}
result.Append(name.AsSpan(lastPos, pos - lastPos));
lastPos = pos;
}
result.Append(name.AsSpan(lastPos));

return result.ToString();
}

public static string[] GetLogicalDrives() => Interop.Sys.GetAllMountPoints();

private static bool Is64BitOperatingSystemWhen32BitProcess => false;

public static string MachineName
{
get
Expand All @@ -60,13 +24,24 @@ public static string MachineName
}
}

private static int GetCurrentProcessId() => Interop.Sys.GetPid();

internal const string NewLineConst = "\n";

public static string SystemDirectory => GetFolderPathCore(SpecialFolder.System, SpecialFolderOption.None);
public static long WorkingSet
{
get
{
Type? processType = Type.GetType("System.Diagnostics.Process, System.Diagnostics.Process, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
if (processType?.GetMethod("GetCurrentProcess")?.Invoke(null, BindingFlags.DoNotWrapExceptions, null, null, null) is IDisposable currentProcess)
{
using (currentProcess)
{
if (processType!.GetMethod("get_WorkingSet64")?.Invoke(currentProcess, BindingFlags.DoNotWrapExceptions, null, null, null) is long result)
return result;
}
}

public static int SystemPageSize => CheckedSysConf(Interop.Sys.SysConfName._SC_PAGESIZE);
// Could not get the current working set.
return 0;
}
}

public static unsafe string UserName
{
Expand Down Expand Up @@ -99,76 +74,5 @@ public static unsafe string UserName

}
}

private static unsafe bool TryGetUserNameFromPasswd(byte* buf, int bufLen, out string? username)
{
// Call getpwuid_r to get the passwd struct
Interop.Sys.Passwd passwd;
int error = Interop.Sys.GetPwUidR(Interop.Sys.GetEUid(), out passwd, buf, bufLen);

// If the call succeeds, give back the user name retrieved
if (error == 0)
{
Debug.Assert(passwd.Name != null);
username = Marshal.PtrToStringAnsi((IntPtr)passwd.Name);
return true;
}

// If the current user's entry could not be found, give back null,
// but still return true (false indicates the buffer was too small).
if (error == -1)
{
username = null;
return true;
}

var errorInfo = new Interop.ErrorInfo(error);

// If the call failed because the buffer was too small, return false to
// indicate the caller should try again with a larger buffer.
if (errorInfo.Error == Interop.Error.ERANGE)
{
username = null;
return false;
}

// Otherwise, fail.
throw new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno);
}

public static string UserDomainName => MachineName;

/// <summary>Invoke <see cref="Interop.Sys.SysConf"/>, throwing if it fails.</summary>
private static int CheckedSysConf(Interop.Sys.SysConfName name)
{
long result = Interop.Sys.SysConf(name);
if (result == -1)
{
Interop.ErrorInfo errno = Interop.Sys.GetLastErrorInfo();
throw errno.Error == Interop.Error.EINVAL ?
new ArgumentOutOfRangeException(nameof(name), name, errno.GetErrorMessage()) :
Interop.GetIOException(errno);
}
return (int)result;
}

public static long WorkingSet
{
get
{
Type? processType = Type.GetType("System.Diagnostics.Process, System.Diagnostics.Process, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
if (processType?.GetMethod("GetCurrentProcess")?.Invoke(null, BindingFlags.DoNotWrapExceptions, null, null, null) is IDisposable currentProcess)
{
using (currentProcess)
{
if (processType!.GetMethod("get_WorkingSet64")?.Invoke(currentProcess, BindingFlags.DoNotWrapExceptions, null, null, null) is long result)
return result;
}
}

// Could not get the current working set.
return 0;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

namespace System
{
public static partial class Environment
{
public static bool UserInteractive => true;

private static string CurrentDirectoryCore
{
get => Interop.Sys.GetCwd();
set => Interop.CheckIo(Interop.Sys.ChDir(value), value, isDirectory: true);
}

private static string ExpandEnvironmentVariablesCore(string name)
{
var result = new ValueStringBuilder(stackalloc char[128]);

int lastPos = 0, pos;
while (lastPos < name.Length && (pos = name.IndexOf('%', lastPos + 1)) >= 0)
{
if (name[lastPos] == '%')
{
string key = name.Substring(lastPos + 1, pos - lastPos - 1);
string? value = GetEnvironmentVariable(key);
if (value != null)
{
result.Append(value);
lastPos = pos + 1;
continue;
}
}
result.Append(name.AsSpan(lastPos, pos - lastPos));
lastPos = pos;
}
result.Append(name.AsSpan(lastPos));

return result.ToString();
}

private static bool Is64BitOperatingSystemWhen32BitProcess => false;

private static int GetCurrentProcessId() => Interop.Sys.GetPid();

internal const string NewLineConst = "\n";

public static string SystemDirectory => GetFolderPathCore(SpecialFolder.System, SpecialFolderOption.None);

public static int SystemPageSize => CheckedSysConf(Interop.Sys.SysConfName._SC_PAGESIZE);

private static unsafe bool TryGetUserNameFromPasswd(byte* buf, int bufLen, out string? username)
steveisok marked this conversation as resolved.
Show resolved Hide resolved
{
// Call getpwuid_r to get the passwd struct
Interop.Sys.Passwd passwd;
int error = Interop.Sys.GetPwUidR(Interop.Sys.GetEUid(), out passwd, buf, bufLen);

// If the call succeeds, give back the user name retrieved
if (error == 0)
{
Debug.Assert(passwd.Name != null);
username = Marshal.PtrToStringAnsi((IntPtr)passwd.Name);
return true;
}

// If the current user's entry could not be found, give back null,
// but still return true (false indicates the buffer was too small).
if (error == -1)
{
username = null;
return true;
}

var errorInfo = new Interop.ErrorInfo(error);

// If the call failed because the buffer was too small, return false to
// indicate the caller should try again with a larger buffer.
if (errorInfo.Error == Interop.Error.ERANGE)
{
username = null;
return false;
}

// Otherwise, fail.
throw new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno);
}

public static string UserDomainName => MachineName;

/// <summary>Invoke <see cref="Interop.Sys.SysConf"/>, throwing if it fails.</summary>
private static int CheckedSysConf(Interop.Sys.SysConfName name)
{
long result = Interop.Sys.SysConf(name);
if (result == -1)
{
Interop.ErrorInfo errno = Interop.Sys.GetLastErrorInfo();
throw errno.Error == Interop.Error.EINVAL ?
new ArgumentOutOfRangeException(nameof(name), name, errno.GetErrorMessage()) :
Interop.GetIOException(errno);
}
return (int)result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public void RelativeSearchPath_Is_Null()
}

[Fact]
[PlatformSpecific(~TestPlatforms.Browser)] // throws pNSE
mdh1418 marked this conversation as resolved.
Show resolved Hide resolved
public void TargetFrameworkTest()
{
const int ExpectedExitCode = 0;
Expand Down Expand Up @@ -129,7 +130,7 @@ public void FriendlyName()

// GetEntryAssembly may be null (i.e. desktop)
if (expected == null)
expected = Assembly.GetExecutingAssembly().GetName().Name;
expected = "DefaultDomain";

Assert.Equal(expected, s);
}
Expand Down Expand Up @@ -371,6 +372,7 @@ public void ReflectionOnlyGetAssemblies()
}

[Fact]
[PlatformSpecific(~TestPlatforms.Browser)] // Throws PNSE
public void MonitoringIsEnabled()
{
Assert.True(AppDomain.MonitoringIsEnabled);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public static void ExitCode_Roundtrips(int exitCode)
[InlineData(1)] // setting ExitCode and exiting Main
[InlineData(2)] // setting ExitCode both from Main and from an Unloading event handler.
[InlineData(3)] // using Exit(exitCode)
[PlatformSpecific(~TestPlatforms.Browser)] // throws PNSE
mdh1418 marked this conversation as resolved.
Show resolved Hide resolved
public static void ExitCode_VoidMainAppReturnsSetValue(int mode)
{
int expectedExitCode = 123;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ internal static string GetComputerName()
#if !Unix
return Environment.GetEnvironmentVariable("COMPUTERNAME");
#else
if (PlatformDetection.IsBrowser)
return "emscripten";
string temp = Interop.Sys.GetNodeName();
int index = temp.IndexOf('.');
return index < 0 ? temp : temp.Substring(0, index);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public TestClass()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/38995", TestPlatforms.Browser)]
public void StackTraceDoesNotStartWithInternalFrame()
{
string stackTrace = Environment.StackTrace;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,10 @@ public void Version_Valid()
[Fact]
public void WorkingSet_Valid()
{
Assert.True(Environment.WorkingSet > 0, "Expected positive WorkingSet value");
if (PlatformDetection.IsBrowser)
Assert.Equal(0, Environment.WorkingSet);
else
Assert.True(Environment.WorkingSet > 0, "Expected positive WorkingSet value");
}

[Trait(XunitConstants.Category, XunitConstants.IgnoreForCI)] // fail fast crashes the process
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,6 @@ public static TheoryData<string, string> GetFullPath_BasicExpansions
{ currentDirectory, currentDirectory },
// "." => current directory
{ ".", currentDirectory },
// ".." => up a directory
{ "..", Path.GetDirectoryName(currentDirectory) },
// "dir/./././." => "dir"
{ Path.Combine(currentDirectory, ".", ".", ".", ".", "."), currentDirectory },
// "dir///." => "dir"
Expand All @@ -234,6 +232,12 @@ public static TheoryData<string, string> GetFullPath_BasicExpansions
{ root + new string(Path.DirectorySeparatorChar, 3), root },
};

if (currentDirectory != Path.GetPathRoot(currentDirectory))
safern marked this conversation as resolved.
Show resolved Hide resolved
{
// ".." => up a directory
data.Add("..", Path.GetDirectoryName(currentDirectory));
}

// Path longer than MaxPath that normalizes down to less than MaxPath
const int Iters = 10000;
var longPath = new StringBuilder(currentDirectory, currentDirectory.Length + (Iters * 2));
Expand Down
Loading