/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="arg1">The first argument to pass to the method.</param> /// <param name="arg2">The second argument to pass to the method.</param> /// <param name="arg3">The third argument to pass to the method.</param> /// <param name="options">Options to use for the invocation.</param> internal static RemoteInvokeHandle RemoteInvoke( Func<string, string, string, int> method, string arg1, string arg2, string arg3, RemoteInvokeOptions options = null) { return RemoteInvoke(method.GetMethodInfo(), new[] { arg1, arg2, arg3 }, options); }
public static void GetGeneration_WeakReference() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.TimeOut = TimeoutMilliseconds; RemoteInvoke(() => { Func<WeakReference> getweakref = delegate () { Version myobj = new Version(); var wkref = new WeakReference(myobj); Assert.True(GC.TryStartNoGCRegion(1024)); Assert.True(GC.GetGeneration(wkref) >= 0); Assert.Equal(GC.GetGeneration(wkref), GC.GetGeneration(myobj)); GC.EndNoGCRegion(); myobj = null; return wkref; }; WeakReference weakref = getweakref(); Assert.True(weakref != null); #if !DEBUG GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true); Assert.Throws<ArgumentNullException>(() => GC.GetGeneration(weakref)); #endif return SuccessExitCode; }, options).Dispose(); }
public static void GetTypeByNameTypeloadFailure() { RemoteInvokeOptions options = new RemoteInvokeOptions(); RemoteInvoke(() => { string test1 = testtype; //Loading from the wrong path Assert.Throws<System.IO.FileNotFoundException>(() => Type.GetType(test1, (aName) => aName.Name == "Foo" ? Assembly.LoadFrom(@".\TestLoadAssembly.dll") : null, typeloader, true )); //Type specified 'Program2' does not exst string test2 = "System.Collections.Generic.Dictionary`2[[Program, TestLoadAssembly], [Program2, TestLoadAssembly]]"; Assert.Throws<TypeLoadException>(() => Type.GetType(test2, assemblyloader, typeloader, true)); //Api does not throw Type t1 = Type.GetType(test2, assemblyloader, typeloader, false //no throw ); Assert.Null(t1); return SuccessExitCode; }, options).Dispose(); }
private static void RunRemote(Func<int> func, ProcessStartInfo psi = null) { var options = new RemoteInvokeOptions(); if (psi != null) { options.StartInfo = psi; } RemoteInvoke(func, options).Dispose(); }
public static void GCNotificationTests(bool approach, int timeout) { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.TimeOut = TimeoutMilliseconds; RemoteInvoke(() => { TestWait(approach, timeout); 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 GetTypeByName() { RemoteInvokeOptions options = new RemoteInvokeOptions(); RemoteInvoke(() => { string test1 = testtype; Type t1 = Type.GetType(test1, (aName) => aName.Name == "Foo" ? Assembly.LoadFrom(destTestAssemblyPath) : 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); return SuccessExitCode; }, options).Dispose(); }
/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="args">The arguments to pass to the method.</param> /// <param name="start">true if this function should Start the Process; false if that responsibility is left up to the caller.</param> /// <param name="psi">The ProcessStartInfo to use, or null for a default.</param> private static RemoteInvokeHandle RemoteInvoke(MethodInfo method, string[] args, RemoteInvokeOptions options) { options = options ?? new RemoteInvokeOptions(); // Verify the specified method is and that it returns an int (the exit code), // and that if it accepts any arguments, they're all strings. Assert.True(method.ReturnType == typeof(int) || method.ReturnType == typeof(Task <int>)); Assert.All(method.GetParameters(), pi => Assert.Equal(typeof(string), pi.ParameterType)); // And make sure it's in this assembly. This isn't critical, but it helps with deployment to know // that the method to invoke is available because we're already running in this assembly. Type t = method.DeclaringType; Assembly a = t.GetTypeInfo().Assembly; Assert.Equal(typeof(RemoteExecutorTestBase).GetTypeInfo().Assembly, a); // Start the other process and return a wrapper for it to handle its lifetime and exit checking. var psi = options.StartInfo; psi.UseShellExecute = false; if (!options.EnableProfiling) { // Profilers / code coverage tools doing coverage of the test process set environment // variables to tell the targeted process what profiler to load. We don't want the child process // to be profiled / have code coverage, so we remove these environment variables for that process // before it's started. psi.Environment.Remove("Cor_Profiler"); psi.Environment.Remove("Cor_Enable_Profiling"); psi.Environment.Remove("CoreClr_Profiler"); psi.Environment.Remove("CoreClr_Enable_Profiling"); } // If we need the host (if it exists), use it, otherwise target the console app directly. string testConsoleAppArgs = "\"" + a.FullName + "\" " + t.FullName + " " + method.Name + " " + string.Join(" ", args); if (!File.Exists(TestConsoleApp)) { throw new IOException("RemoteExecutorConsoleApp test app isn't present in the test runtime directory."); } if (IsFullFramework) { psi.FileName = TestConsoleApp; psi.Arguments = testConsoleAppArgs; } else { psi.FileName = HostRunner; psi.Arguments = TestConsoleApp + " " + testConsoleAppArgs; } // Return the handle to the process, which may or not be started return(new RemoteInvokeHandle(options.Start ? Process.Start(psi) : new Process() { StartInfo = psi }, options)); }
/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="args">The arguments to pass to the method.</param> /// <param name="start">true if this function should Start the Process; false if that responsibility is left up to the caller.</param> /// <param name="psi">The ProcessStartInfo to use, or null for a default.</param> private static RemoteInvokeHandle RemoteInvoke(MethodInfo method, string[] args, RemoteInvokeOptions options) { options = options ?? new RemoteInvokeOptions(); // Verify the specified method is and that it returns an int (the exit code), // and that if it accepts any arguments, they're all strings. Assert.Equal(typeof(int), method.ReturnType); Assert.All(method.GetParameters(), pi => Assert.Equal(typeof(string), pi.ParameterType)); // And make sure it's in this assembly. This isn't critical, but it helps with deployment to know // that the method to invoke is available because we're already running in this assembly. Type t = method.DeclaringType; Assembly a = t.GetTypeInfo().Assembly; Assert.Equal(typeof(RemoteExecutorTestBase).GetTypeInfo().Assembly, a); // Start the other process and return a wrapper for it to handle its lifetime and exit checking. var psi = options.StartInfo; psi.FileName = HostRunner; psi.Arguments = TestConsoleApp + " \"" + a.FullName + "\" " + t.FullName + " " + method.Name + " " + string.Join(" ", args); psi.UseShellExecute = false; if (!options.EnableProfiling) { // Profilers / code coverage tools doing coverage of the test process set environment // variables to tell the targeted process what profiler to load. We don't want the child process // to be profiled / have code coverage, so we remove these environment variables for that process // before it's started. psi.Environment.Remove("Cor_Profiler"); psi.Environment.Remove("Cor_Enable_Profiling"); psi.Environment.Remove("CoreClr_Profiler"); psi.Environment.Remove("CoreClr_Enable_Profiling"); } // Return the handle to the process, which may or not be started return new RemoteInvokeHandle(options.Start ? Process.Start(psi) : new Process() { StartInfo = psi }); }
/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="args">The arguments to pass to the method.</param> /// <param name="options">Options to use for the invocation.</param> internal static RemoteInvokeHandle RemoteInvokeRaw(Delegate method, string unparsedArg, RemoteInvokeOptions options = null) { return RemoteInvoke(method.GetMethodInfo(), new[] { unparsedArg }, options); }
/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="options">Options to use for the invocation.</param> public static RemoteInvokeHandle RemoteInvoke( Func <Task <int> > method, RemoteInvokeOptions options = null) { return(RemoteInvoke(GetMethodInfo(method), Array.Empty <string>(), options)); }
/// <summary>Invokes the method from this assembly in another process using the specified arguments without performing any modifications to the arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="args">The arguments to pass to the method.</param> /// <param name="options">Options to use for the invocation.</param> public static RemoteInvokeHandle RemoteInvokeRaw(Delegate method, string unparsedArg, RemoteInvokeOptions options = null) { return(RemoteInvoke(GetMethodInfo(method), new[] { unparsedArg }, options, pasteArguments: false)); }
/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="args">The arguments to pass to the method.</param> /// <param name="start">true if this function should Start the Process; false if that responsibility is left up to the caller.</param> /// <param name="psi">The ProcessStartInfo to use, or null for a default.</param> /// <param name="pasteArguments">true if this function should paste the arguments (e.g. surrounding with quotes); false if that responsibility is left up to the caller.</param> private static RemoteInvokeHandle RemoteInvoke(MethodInfo method, string[] args, RemoteInvokeOptions options, bool pasteArguments = true) { options = options ?? new RemoteInvokeOptions(); // Verify the specified method returns an int (the exit code) or nothing, // and that if it accepts any arguments, they're all strings. Assert.True(method.ReturnType == typeof(void) || method.ReturnType == typeof(int) || method.ReturnType == typeof(Task <int>)); Assert.All(method.GetParameters(), pi => Assert.Equal(typeof(string), pi.ParameterType)); // And make sure it's in this assembly. This isn't critical, but it helps with deployment to know // that the method to invoke is available because we're already running in this assembly. Type t = method.DeclaringType; Assembly a = t.GetTypeInfo().Assembly; // Start the other process and return a wrapper for it to handle its lifetime and exit checking. ProcessStartInfo psi = options.StartInfo; psi.UseShellExecute = false; if (!options.EnableProfiling) { // Profilers / code coverage tools doing coverage of the test process set environment // variables to tell the targeted process what profiler to load. We don't want the child process // to be profiled / have code coverage, so we remove these environment variables for that process // before it's started. psi.Environment.Remove("Cor_Profiler"); psi.Environment.Remove("Cor_Enable_Profiling"); psi.Environment.Remove("CoreClr_Profiler"); psi.Environment.Remove("CoreClr_Enable_Profiling"); } // If we need the host (if it exists), use it, otherwise target the console app directly. string metadataArgs = PasteArguments.Paste(new string[] { a.FullName, t.FullName, method.Name, options.ExceptionFile }, pasteFirstArgumentUsingArgV0Rules: false); string passedArgs = pasteArguments ? PasteArguments.Paste(args, pasteFirstArgumentUsingArgV0Rules: false) : string.Join(" ", args); string testConsoleAppArgs = ExtraParameter + " " + metadataArgs + " " + passedArgs; // Uap console app is globally registered. if (!File.Exists(HostRunner) && !PlatformDetection.IsUap) { throw new IOException($"{HostRunner} test app isn't present in the test runtime directory."); } if (options.RunAsSudo) { psi.FileName = "sudo"; psi.Arguments = HostRunner + " " + testConsoleAppArgs; } else { psi.FileName = HostRunner; psi.Arguments = testConsoleAppArgs; } // Return the handle to the process, which may or not be started return(new RemoteInvokeHandle(options.Start ? Process.Start(psi) : new Process() { StartInfo = psi }, options, a.FullName, t.FullName, method.Name )); }
public RemoteInvokeHandle(Process process, RemoteInvokeOptions options) { Process = process; Options = options; }
/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="options">Options to use for the invocation.</param> internal static RemoteInvokeHandle RemoteInvoke( Func <int> method, RemoteInvokeOptions options = null) { return(RemoteInvoke(method.GetMethodInfo(), Array.Empty <string>(), options)); }
/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="args">The arguments to pass to the method.</param> /// <param name="options">Options to use for the invocation.</param> internal static RemoteInvokeHandle RemoteInvokeRaw(Delegate method, string unparsedArg, RemoteInvokeOptions options = null) { return(RemoteInvoke(method.GetMethodInfo(), new[] { unparsedArg }, options)); }
public static void TryStartNoGCRegionNegTest() { RemoteInvokeOptions options = new RemoteInvokeOptions(); options.TimeOut = TimeoutMilliseconds; RemoteInvoke(() => { Assert.Throws<InvalidOperationException>(() => GC.EndNoGCRegion()); Assert.True(GC.TryStartNoGCRegion(1024)); Assert.Throws<InvalidOperationException>(() => GC.TryStartNoGCRegion(1024)); Assert.True(GC.TryStartNoGCRegion(1024, true)); Assert.Throws<InvalidOperationException>(() => GC.TryStartNoGCRegion(1024, true)); Assert.True(GC.TryStartNoGCRegion(1024, 1024)); Assert.Throws<InvalidOperationException>(() => GC.TryStartNoGCRegion(1024, 1024)); Assert.True(GC.TryStartNoGCRegion(1024, 1024, true)); Assert.Throws<InvalidOperationException>(() => GC.TryStartNoGCRegion(1024, 1024, true)); Assert.True(GC.TryStartNoGCRegion(1024, true)); Assert.Equal(GCSettings.LatencyMode, GCLatencyMode.NoGCRegion); Assert.Throws<InvalidOperationException>(() => GCSettings.LatencyMode = GCLatencyMode.LowLatency); GC.EndNoGCRegion(); return SuccessExitCode; }, options).Dispose(); }
/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="options">Options to use for the invocation.</param> internal static RemoteInvokeHandle RemoteInvoke( Func<int> method, RemoteInvokeOptions options = null) { return RemoteInvoke(method.GetMethodInfo(), Array.Empty<string>(), options); }
/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="args">The arguments to pass to the method.</param> /// <param name="options"><see cref="System.Diagnostics.RemoteInvokeOptions"/> The options to execute the remote process.</param> /// <param name="pasteArguments">Unused in UAP.</param> private static RemoteInvokeHandle RemoteInvoke(MethodInfo method, string[] args, RemoteInvokeOptions options, bool pasteArguments = false) { options = options ?? new RemoteInvokeOptions(); // Verify the specified method returns an int (the exit code) or nothing, // and that if it accepts any arguments, they're all strings. Assert.True(method.ReturnType == typeof(void) || method.ReturnType == typeof(int) || method.ReturnType == typeof(Task <int>)); Assert.All(method.GetParameters(), pi => Assert.Equal(typeof(string), pi.ParameterType)); // And make sure it's in this assembly. This isn't critical, but it helps with deployment to know // that the method to invoke is available because we're already running in this assembly. Type t = method.DeclaringType; Assembly a = t.GetTypeInfo().Assembly; int exitCode; using (AppServiceConnection remoteExecutionService = new AppServiceConnection()) { // Here, we use the app service name defined in the app service provider's Package.appxmanifest file in the <Extension> section. remoteExecutionService.AppServiceName = "com.microsoft.corefxuaptests"; remoteExecutionService.PackageFamilyName = Package.Current.Id.FamilyName; AppServiceConnectionStatus status = remoteExecutionService.OpenAsync().GetAwaiter().GetResult(); if (status != AppServiceConnectionStatus.Success) { throw new IOException($"RemoteInvoke cannot open the remote service. Open Service Status: {status}"); } ValueSet message = new ValueSet(); message.Add("AssemblyName", a.FullName); message.Add("TypeName", t.FullName); message.Add("MethodName", method.Name); int i = 0; foreach (string arg in args) { message.Add("Arg" + i, arg); i++; } AppServiceResponse response = remoteExecutionService.SendMessageAsync(message).GetAwaiter().GetResult(); Assert.True(response.Status == AppServiceResponseStatus.Success, $"response.Status = {response.Status}"); exitCode = (int)response.Message["Results"]; Assert.True(!options.CheckExitCode || exitCode == options.ExpectedExitCode, (string)response.Message["Log"] + Environment.NewLine + $"Returned Error code: {exitCode}"); } // RemoteInvokeHandle is not really needed in the UAP scenario but we use it just to have consistent interface as non UAP var handle = new RemoteInvokeHandle(null, options, null, null, null); handle.ExitCode = exitCode; return(handle); }
public static void GetTypeByNameCaseSensitiveTypeloadFailure() { RemoteInvokeOptions options = new RemoteInvokeOptions(); RemoteInvoke(() => { //Type load failure due to case sensitive search of type Ptogram string test3 = "System.Collections.Generic.Dictionary`2[[Program, TestLoadAssembly], [program, TestLoadAssembly]]"; Assert.Throws<TypeLoadException>(() => Type.GetType(test3, assemblyloader, typeloader, true, false //case sensitive )); //non throwing version Type t2 = Type.GetType(test3, assemblyloader, typeloader, false, //no throw false ); Assert.Null(t2); return SuccessExitCode; }, options).Dispose(); }