public unsafe void TestCheckChildProcessUserAndGroupIds() { string userName = GetCurrentRealUserName(); string userId = GetUserId(userName); string userGroupId = GetUserGroupId(userName); string userGroupIds = GetUserGroupIds(userName); // If this test runs as the user, we expect to be able to match the user groups exactly. // Except on OSX, where getgrouplist may return a list of groups truncated to NGROUPS_MAX. bool checkGroupsExact = userId == geteuid().ToString() && !RuntimeInformation.IsOSPlatform(OSPlatform.OSX); // Start as username var invokeOptions = new RemoteInvokeOptions(); invokeOptions.StartInfo.UserName = userName; using (RemoteInvokeHandle handle = RemoteExecutor.Invoke(CheckUserAndGroupIds, userId, userGroupId, userGroupIds, checkGroupsExact.ToString(), invokeOptions)) { } }
public static void TryStartNoGCRegion_SettingLatencyMode_ThrowsInvalidOperationException() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.TimeOut = TimeoutMilliseconds; RemoteExecutor.Invoke(() => { // The budget for this test is 4mb, because the act of throwing an exception with a message // contained in a System.Private.CoreLib resource file has to potential to allocate a lot. // // In addition to this, the Assert.Throws xunit combinator tends to also allocate a lot. Assert.True(GC.TryStartNoGCRegion(4000 * 1024, true)); Assert.Equal(GCLatencyMode.NoGCRegion, GCSettings.LatencyMode); Assert.Throws <InvalidOperationException>(() => GCSettings.LatencyMode = GCLatencyMode.LowLatency); GC.EndNoGCRegion(); }, options).Dispose(); }
public void ReturnsResourceWhenFeatureSwitchIsDisabled() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.RuntimeConfigurationOptions.Add("System.Resources.UseSystemResourceKeys", false); RemoteExecutor.Invoke(() => { try { throw new ArgumentException(); } catch (Exception e) { Assert.NotEqual("AggregateException_ctor_DefaultMessage", e.Message); } }, options).Dispose(); }
public static void GCNotifiicationTests() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.TimeOut = TimeoutMilliseconds; RemoteInvoke(() => { Assert.True(TestWait(true, -1)); Assert.True(TestWait(false, -1)); Assert.True(TestWait(true, 0)); Assert.True(TestWait(false, 0)); Assert.True(TestWait(true, 100)); Assert.True(TestWait(false, 100)); Assert.True(TestWait(true, int.MaxValue)); Assert.True(TestWait(false, int.MaxValue)); return(SuccessExitCode); }, options).Dispose(); }
public void UnhandledException_Called() { System.IO.File.Delete("success.txt"); RemoteInvokeOptions options = new RemoteInvokeOptions(); options.CheckExitCode = false; RemoteInvoke(() => { AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); throw new Exception("****This Unhandled Exception is Expected****"); #pragma warning disable 0162 return(SuccessExitCode); #pragma warning restore 0162 }, options).Dispose(); Assert.True(System.IO.File.Exists("success.txt")); }
public static void SetMinMaxThreadsTest_ChangedInDotNetCore() { RemoteExecutor.Invoke(() => { int minw, minc, maxw, maxc; ThreadPool.GetMinThreads(out minw, out minc); ThreadPool.GetMaxThreads(out maxw, out maxc); try { Assert.True(ThreadPool.SetMinThreads(0, 0)); VerifyMinThreads(1, 1); Assert.False(ThreadPool.SetMaxThreads(0, 1)); Assert.False(ThreadPool.SetMaxThreads(1, 0)); VerifyMaxThreads(maxw, maxc); } finally { Assert.True(ThreadPool.SetMaxThreads(maxw, maxc)); VerifyMaxThreads(maxw, maxc); Assert.True(ThreadPool.SetMinThreads(minw, minc)); VerifyMinThreads(minw, minc); } }).Dispose(); // Verify that SetMinThreads() and SetMaxThreads() return false when trying to set a different value from what is // configured through config var options = new RemoteInvokeOptions(); options.RuntimeConfigurationOptions["System.Threading.ThreadPool.MinThreads"] = "1"; options.RuntimeConfigurationOptions["System.Threading.ThreadPool.MaxThreads"] = "2"; RemoteExecutor.Invoke(() => { int w, c; ThreadPool.GetMinThreads(out w, out c); Assert.Equal(1, w); ThreadPool.GetMaxThreads(out w, out c); Assert.Equal(2, w); Assert.True(ThreadPool.SetMinThreads(1, 1)); Assert.True(ThreadPool.SetMaxThreads(2, 1)); Assert.False(ThreadPool.SetMinThreads(2, 1)); Assert.False(ThreadPool.SetMaxThreads(1, 1)); }, options).Dispose(); }
[PlatformSpecific(TestPlatforms.AnyUnix)] // SIGTERM signal. public void SigTermExitCode(int?exitCodeOnSigterm) { Action <string> action = (string sigTermExitCode) => { if (!string.IsNullOrEmpty(sigTermExitCode)) { AppDomain.CurrentDomain.ProcessExit += (sender, args) => { Assert.Same(AppDomain.CurrentDomain, sender); Environment.ExitCode = int.Parse(sigTermExitCode); }; } Console.WriteLine("Application started"); // Wait for SIGTERM System.Threading.Thread.Sleep(int.MaxValue); }; RemoteInvokeOptions options = new RemoteInvokeOptions(); options.StartInfo.RedirectStandardOutput = true; options.CheckExitCode = false; using (RemoteInvokeHandle remoteExecution = RemoteExecutor.Invoke(action, exitCodeOnSigterm?.ToString() ?? string.Empty, options)) { Process process = remoteExecution.Process; // Wait for the process to start and register the ProcessExit handler string processOutput = process.StandardOutput.ReadLine(); Assert.Equal("Application started", processOutput); // Send SIGTERM int rv = kill(process.Id, SIGTERM); Assert.Equal(0, rv); // Process exits in a timely manner bool exited = process.WaitForExit(RemoteExecutor.FailWaitTimeoutMilliseconds); Assert.True(exited); // Check exit code Assert.Equal(exitCodeOnSigterm ?? 128 + SIGTERM, process.ExitCode); } }
public void SerializeAndDeserializeWithSettingsSerializeAsBinary() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.RuntimeConfigurationOptions.Add("System.Configuration.ConfigurationManager.EnableUnsafeBinaryFormatterInPropertyValueSerialization", bool.TrueString); RemoteExecutor.Invoke(() => { #pragma warning disable CS0618 // Type or member is obsolete SettingsProperty property = new SettingsProperty("Binary", typeof(string), null, false, "AString", SettingsSerializeAs.Binary, new SettingsAttributeDictionary(), true, true); #pragma warning restore CS0618 // Type or member is obsolete SettingsPropertyValue value = new SettingsPropertyValue(property); value.PropertyValue = "AString"; // To force _changedSinceLastSerialized to true to allow for serialization in the next call object serializedValue = value.SerializedValue; Assert.NotNull(serializedValue); value.Deserialized = false; object deserializedValue = value.PropertyValue; Assert.Equal("AString", deserializedValue); }, options).Dispose(); }
public unsafe void TestCheckChildProcessUserAndGroupIdsElevated(bool useRootGroups) { Func <string, string, int> runsAsRoot = (string username, string useRootGroupsArg) => { // Verify we are root Assert.Equal(0U, getuid()); Assert.Equal(0U, geteuid()); Assert.Equal(0U, getgid()); Assert.Equal(0U, getegid()); string userId = GetUserId(username); string userGroupId = GetUserGroupId(username); string userGroupIds = GetUserGroupIds(username); if (bool.Parse(useRootGroupsArg)) { uint rootGroups = 0; int setGroupsRv = setgroups(1, &rootGroups); Assert.Equal(0, setGroupsRv); } // On systems with a low value of NGROUPS_MAX (e.g 16 on OSX), the groups may be truncated. // On Linux NGROUPS_MAX is 65536, so we expect to see every group. bool checkGroupsExact = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); // Start as username var invokeOptions = new RemoteInvokeOptions(); invokeOptions.StartInfo.UserName = username; using (RemoteInvokeHandle handle = RemoteExecutor.Invoke(CheckUserAndGroupIds, userId, userGroupId, userGroupIds, checkGroupsExact.ToString(), invokeOptions)) { } return(RemoteExecutor.SuccessExitCode); }; // Start as root string userName = GetCurrentRealUserName(); using (RemoteInvokeHandle handle = RemoteExecutor.Invoke(runsAsRoot, userName, useRootGroups.ToString(), new RemoteInvokeOptions { RunAsSudo = true })) { } }
[PlatformSpecific(TestPlatforms.AnyUnix)] // Inline Socket mode is specific to Unix Socket implementation. public void InlineSocketContinuations() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.StartInfo.EnvironmentVariables.Add("DOTNET_SYSTEM_NET_SOCKETS_INLINE_COMPLETIONS", "1"); options.TimeOut = (int)TimeSpan.FromMinutes(20).TotalMilliseconds; RemoteExecutor.Invoke(async() => { // Connect/Accept tests await new AcceptEap(null).Accept_ConcurrentAcceptsBeforeConnects_Success(5); await new AcceptEap(null).Accept_ConcurrentAcceptsAfterConnects_Success(5); // Send/Receive tests await new SendReceive_Eap(null).SendRecv_Stream_TCP(IPAddress.Loopback, useMultipleBuffers: false); await new SendReceive_Eap(null).SendRecv_Stream_TCP_MultipleConcurrentReceives(IPAddress.Loopback, useMultipleBuffers: false); await new SendReceive_Eap(null).SendRecv_Stream_TCP_MultipleConcurrentSends(IPAddress.Loopback, useMultipleBuffers: false); await new SendReceive_Eap(null).TcpReceiveSendGetsCanceledByDispose(receiveOrSend: true, ipv6Server: false, dualModeClient: false); await new SendReceive_Eap(null).TcpReceiveSendGetsCanceledByDispose(receiveOrSend: false, ipv6Server: false, dualModeClient: false); }, options).Dispose(); }
private void RunTestAsSudo(Func <string, int> testMethod, string arg) { RemoteInvokeOptions options = new RemoteInvokeOptions() { Start = false, RunAsSudo = true }; Process p = null; using (RemoteInvokeHandle handle = RemoteInvoke(testMethod, arg, options)) { p = handle.Process; handle.Process = null; } AddProcessForDispose(p); p.Start(); p.WaitForExit(); Assert.Equal(0, p.ExitCode); }
public void HttpProxy_TryCreate_CaseInsensitiveVariables(string proxyEnvVar, string noProxyEnvVar) { string proxy = "http://*****:*****@1.1.1.1:3000"; var options = new RemoteInvokeOptions(); options.StartInfo.EnvironmentVariables.Add(proxyEnvVar, proxy); options.StartInfo.EnvironmentVariables.Add(noProxyEnvVar, ".test.com, foo.com"); RemoteExecutor.Invoke((proxy) => { var directUri = new Uri("http://test.com"); var thruProxyUri = new Uri("http://atest.com"); Assert.True(HttpEnvironmentProxy.TryCreate(out IWebProxy p)); Assert.NotNull(p); Assert.True(p.IsBypassed(directUri)); Assert.False(p.IsBypassed(thruProxyUri)); Assert.Equal(new Uri(proxy), p.GetProxy(thruProxyUri)); }, proxy, options).Dispose(); }
public static void DisabledThroughFeatureSwitch() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.RuntimeConfigurationOptions[EnableBinaryFormatterSwitchName] = bool.FalseString; RemoteExecutor.Invoke(() => { // First, test serialization MemoryStream ms = new MemoryStream(); BinaryFormatter bf = new BinaryFormatter(); var ex = Assert.Throws <NotSupportedException>(() => bf.Serialize(ms, "A string to serialize.")); Assert.Contains(MoreInfoUrl, ex.Message, StringComparison.Ordinal); // error message should link to the more info URL // Then test deserialization ex = Assert.Throws <NotSupportedException>(() => bf.Deserialize(ms)); Assert.Contains(MoreInfoUrl, ex.Message, StringComparison.Ordinal); // error message should link to the more info URL }, options).Dispose(); }
public static void TryStartNoGCRegion_SettingLatencyMode_ThrowsInvalidOperationException() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.TimeOut = TimeoutMilliseconds; RemoteInvoke(() => { // The budget for this test is 4mb, because the act of throwing an exception with a message // contained in a resource file has to potential to allocate a lot on CoreRT. In particular, when compiling // in multi-file mode, this will trigger a resource lookup in System.Private.CoreLib. // // In addition to this, the Assert.Throws xunit combinator tends to also allocate a lot. Assert.True(GC.TryStartNoGCRegion(4000 * 1024, true)); Assert.Equal(GCSettings.LatencyMode, GCLatencyMode.NoGCRegion); Assert.Throws <InvalidOperationException>(() => GCSettings.LatencyMode = GCLatencyMode.LowLatency); GC.EndNoGCRegion(); return(SuccessExitCode); }, options).Dispose(); }
public static void SerializeAndDeserialize(bool useBinaryFormatter, string key) { RemoteInvokeOptions options = new RemoteInvokeOptions(); if (useBinaryFormatter) { options.RuntimeConfigurationOptions.Add(enableBinaryFormatterInTypeConverter, bool.TrueString); } RemoteExecutor.Invoke((key) => { var context = new DesigntimeLicenseContext(); context.SetSavedLicenseKey(typeof(int), key); var assembly = typeof(DesigntimeLicenseContextSerializer).Assembly; Type runtimeLicenseContextType = assembly.GetType("System.ComponentModel.Design.RuntimeLicenseContext"); Assert.NotNull(runtimeLicenseContextType); object runtimeLicenseContext = Activator.CreateInstance(runtimeLicenseContextType); FieldInfo _savedLicenseKeys = runtimeLicenseContextType.GetField("_savedLicenseKeys", BindingFlags.NonPublic | BindingFlags.Instance); Assert.NotNull(_savedLicenseKeys); _savedLicenseKeys.SetValue(runtimeLicenseContext, new Hashtable()); Assert.NotNull(runtimeLicenseContext); Type designtimeLicenseContextSerializer = assembly.GetType("System.ComponentModel.Design.DesigntimeLicenseContextSerializer"); Assert.NotNull(designtimeLicenseContextSerializer); MethodInfo deserializeMethod = designtimeLicenseContextSerializer.GetMethod("Deserialize", BindingFlags.NonPublic | BindingFlags.Static); using (MemoryStream stream = new MemoryStream()) { long position = stream.Position; DesigntimeLicenseContextSerializer.Serialize(stream, key, context); stream.Seek(position, SeekOrigin.Begin); VerifyStreamFormatting(stream); deserializeMethod.Invoke(null, new object[] { stream, key, runtimeLicenseContext }); Hashtable savedLicenseKeys = runtimeLicenseContext.GetType().GetField("_savedLicenseKeys", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(runtimeLicenseContext) as Hashtable; Assert.NotNull(savedLicenseKeys); var value = savedLicenseKeys[typeof(int).AssemblyQualifiedName]; Assert.True(value is string); Assert.Equal(key, value); } }, key, options).Dispose(); }
private void HandlerInvokedForSignal(int signalOuter, bool redirectStandardInput) { // On Windows we could use GenerateConsoleCtrlEvent to send a ctrl-C to the process, // however that'll apply to all processes associated with the same group, which will // include processes like the code coverage tool when doing code coverage runs, causing // those other processes to exit. As such, we test this only on Unix, where we can // send a SIGINT signal to this specific process only. // This test sends a SIGINT back to itself... if run in the xunit process, this would end // up canceling the rest of xunit's tests. So we run the test itself in a separate process. RemoteInvokeOptions options = new RemoteInvokeOptions(); options.StartInfo.RedirectStandardInput = redirectStandardInput; RemoteExecutor.Invoke(signalStr => { var tcs = new TaskCompletionSource <ConsoleSpecialKey>(); ConsoleCancelEventHandler handler = (sender, e) => { e.Cancel = true; tcs.SetResult(e.SpecialKey); }; Console.CancelKeyPress += handler; try { int signalInner = int.Parse(signalStr); Assert.Equal(0, kill(Environment.ProcessId, signalInner)); Assert.True(tcs.Task.Wait(WaitFailTestTimeoutSeconds * 1000)); Assert.Equal( signalInner == SIGINT ? ConsoleSpecialKey.ControlC : ConsoleSpecialKey.ControlBreak, tcs.Task.Result); } finally { Console.CancelKeyPress -= handler; } }, signalOuter.ToString(), options).Dispose(); }
[PlatformSpecific(TestPlatforms.Linux)] // s_allowedProgramsToRun is Linux specific public void ProcessStart_UseShellExecute_OnUnix_ValidVerbs(string verb, bool isValid) { // Create a script that we'll use to 'open' the file by putting it on PATH // with the appropriate name. string path = Path.Combine(TestDirectory, "Path"); Directory.CreateDirectory(path); WriteScriptFile(path, s_allowedProgramsToRun[0], returnValue: 42); RemoteInvokeOptions options = new RemoteInvokeOptions(); options.StartInfo.EnvironmentVariables["PATH"] = path; RemoteExecutor.Invoke((argVerb, argValid) => { if (argVerb == "<null>") { argVerb = null; } var psi = new ProcessStartInfo { UseShellExecute = true, FileName = "/", Verb = argVerb }; if (bool.Parse(argValid)) { using (var px = Process.Start(psi)) { Assert.NotNull(px); px.WaitForExit(); Assert.True(px.HasExited); Assert.Equal(42, px.ExitCode); } } else { Assert.Throws <Win32Exception>(() => Process.Start(psi)); } }, verb ?? "<null>", isValid.ToString(), options).Dispose(); }
public void ProcessStart_SkipsNonExecutableFilesOnPATH() { const string ScriptName = "script"; // Create a directory named ScriptName. string path1 = Path.Combine(TestDirectory, "Path1"); Directory.CreateDirectory(Path.Combine(path1, ScriptName)); // Create a non-executable file named ScriptName string path2 = Path.Combine(TestDirectory, "Path2"); Directory.CreateDirectory(path2); File.WriteAllText(Path.Combine(path2, ScriptName), "Not executable"); // Create an executable script named ScriptName string path3 = Path.Combine(TestDirectory, "Path3"); Directory.CreateDirectory(path3); string filename = WriteScriptFile(path3, ScriptName, returnValue: 42); // Process.Start ScriptName with the above on PATH. RemoteInvokeOptions options = new RemoteInvokeOptions(); options.StartInfo.EnvironmentVariables["PATH"] = $"{path1}:{path2}:{path3}"; RemoteExecutor.Invoke(() => { using (var px = Process.Start(new ProcessStartInfo { FileName = ScriptName })) { Assert.NotNull(px); px.WaitForExit(); Assert.True(px.HasExited); Assert.Equal(42, px.ExitCode); } }, options).Dispose(); }
public void GetTypeByName() { RemoteInvokeOptions options = new RemoteInvokeOptions(); RemoteExecutor.Invoke(() => { string test1 = testtype; Type t1 = Type.GetType(test1, (aName) => aName.Name == "Foo" ? Assembly.LoadFrom(s_testAssemblyPath) : null, typeloader, true ); Assert.NotNull(t1); string test2 = "System.Collections.Generic.Dictionary`2[[Program, TestLoadAssembly], [Program, TestLoadAssembly]]"; Type t2 = Type.GetType(test2, assemblyloader, typeloader, true); Assert.NotNull(t2); Assert.Equal(t1, t2); }, options).Dispose(); }
public static void TryStartNoGCRegion_SettingLatencyMode_ThrowsInvalidOperationException() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.TimeOut = TimeoutMilliseconds; RemoteInvoke(() => { // 40kb budget, see below comment Assert.True(GC.TryStartNoGCRegion(40 * 1024, true)); Assert.Equal(GCSettings.LatencyMode, GCLatencyMode.NoGCRegion); // PLEASE NOTE: the xunit Assert.Throws combinator allocates a lot and you should measure // how large the GC budget should be *manually* if you use it while in a no GC region. // // In this case, this particular one allocates 23720 bytes, so a budget of 40k should be // large enough to keep us in a no GC region. Assert.Throws <InvalidOperationException>(() => GCSettings.LatencyMode = GCLatencyMode.LowLatency); GC.EndNoGCRegion(); return(SuccessExitCode); }, options).Dispose(); }
public void DisableIPv6_OSSupportsIPv6_False() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.StartInfo.EnvironmentVariables["DOTNET_SYSTEM_NET_DISABLEIPV6"] = "1"; RemoteExecutor.Invoke(RunTest, options).Dispose();