public void CanParseRuntimeFramework(FrameworkData data) { RuntimeFramework framework = RuntimeFramework.Parse(data.representation); Assert.AreEqual(data.runtime, framework.Runtime); Assert.AreEqual(data.clrVersion, framework.ClrVersion); }
public void DefaultValues(string framework) { _package.Settings[EnginePackageSettings.TargetRuntimeFramework] = framework; var process = GetAgentProcess(); Assert.That(process.AgentArgs.ToString(), Is.EqualTo(REQUIRED_ARGS)); Assert.True(process.EnableRaisingEvents, "EnableRaisingEvents"); var startInfo = process.StartInfo; Assert.False(startInfo.UseShellExecute, "UseShellExecute"); Assert.True(startInfo.CreateNoWindow, "CreateNoWindow"); Assert.False(startInfo.LoadUserProfile, "LoadUserProfile"); var targetRuntime = RuntimeFramework.Parse(framework); if (targetRuntime.Runtime == RuntimeType.Mono) { string monoOptions = "--runtime=v" + targetRuntime.ClrVersion.ToString(3); Assert.That(startInfo.FileName, Is.EqualTo(RuntimeFramework.MonoExePath)); Assert.That(startInfo.Arguments, Is.EqualTo( $"{monoOptions} \"{process.AgentExePath}\" {process.AgentArgs}")); } else { Assert.That(startInfo.FileName, Is.EqualTo(process.AgentExePath)); Assert.That(startInfo.Arguments, Is.EqualTo(process.AgentArgs.ToString())); } }
public void CanParseRuntimeFramework(FrameworkData data) { RuntimeFramework framework = RuntimeFramework.Parse(data.representation); Assert.That(framework.Runtime, Is.EqualTo(data.runtime)); Assert.That(framework.ClrVersion, Is.EqualTo(data.clrVersion)); }
// Any Errors thrown from this method indicate that the client // runner is putting invalid values into the package. private void ValidatePackageSettings() { #if NUNIT_ENGINE // Core engine does not support this setting var frameworkSetting = TestPackage.GetSetting(PackageSettings.RuntimeFramework, ""); if (frameworkSetting.Length > 0) { var runtimeService = Services.GetService <IRuntimeFrameworkService>(); if (!runtimeService.IsAvailable(frameworkSetting)) { throw new NUnitEngineException(string.Format("The requested framework {0} is unknown or not available.", frameworkSetting)); } var processModel = TestPackage.GetSetting(PackageSettings.ProcessModel, "Default"); if (processModel.ToLower() == "single") { var currentFramework = RuntimeFramework.CurrentFramework; var requestedFramework = RuntimeFramework.Parse(frameworkSetting); if (!currentFramework.Supports(requestedFramework)) { throw new NUnitEngineException(string.Format( "Cannot run {0} framework in process already running {1}.", frameworkSetting, currentFramework)); } } } #endif }
// Any Errors thrown from this method indicate that the client // runner is putting invalid values into the package. private void ValidatePackageSettings() { var frameworkSetting = TestPackage.GetSetting(EnginePackageSettings.RuntimeFramework, ""); if (frameworkSetting.Length > 0) { // Check requested framework is actually available var runtimeService = _services.GetService <IRuntimeFrameworkService>(); if (!runtimeService.IsAvailable(frameworkSetting)) { throw new NUnitEngineException(string.Format("The requested framework {0} is unknown or not available.", frameworkSetting)); } // If running in process, check requested framework is compatible var processModel = TestPackage.GetSetting(EnginePackageSettings.ProcessModel, "Default"); if (processModel.ToLower() == "single") { var currentFramework = RuntimeFramework.CurrentFramework; var requestedFramework = RuntimeFramework.Parse(frameworkSetting); if (!currentFramework.Supports(requestedFramework)) { throw new NUnitEngineException(string.Format( "Cannot run {0} framework in process already running {1}.", frameworkSetting, currentFramework)); } } } }
public AgentProcess(TestAgency agency, TestPackage package, Guid agentId) { // Get target runtime string runtimeSetting = package.GetSetting(EnginePackageSettings.TargetRuntimeFramework, ""); TargetRuntime = RuntimeFramework.Parse(runtimeSetting); // Access other package settings bool runAsX86 = package.GetSetting(EnginePackageSettings.RunAsX86, false); bool debugAgent = package.GetSetting(EnginePackageSettings.DebugAgent, false); string traceLevel = package.GetSetting(EnginePackageSettings.InternalTraceLevel, "Off"); bool loadUserProfile = package.GetSetting(EnginePackageSettings.LoadUserProfile, false); string workDirectory = package.GetSetting(EnginePackageSettings.WorkDirectory, string.Empty); AgentArgs = new StringBuilder($"{agentId} {agency.RemotingUrl} --pid={Process.GetCurrentProcess().Id}"); // Set options that need to be in effect before the package // is loaded by using the command line. if (traceLevel != "Off") { AgentArgs.Append(" --trace=").EscapeProcessArgument(traceLevel); } if (debugAgent) { AgentArgs.Append(" --debug-agent"); } if (workDirectory != string.Empty) { AgentArgs.Append(" --work=").EscapeProcessArgument(workDirectory); } AgentExePath = GetTestAgentExePath(TargetRuntime, runAsX86); log.Debug("Using nunit-agent at " + AgentExePath); StartInfo.UseShellExecute = false; StartInfo.CreateNoWindow = true; StartInfo.WorkingDirectory = Environment.CurrentDirectory; EnableRaisingEvents = true; if (TargetRuntime.Runtime == RuntimeType.Mono) { StartInfo.FileName = RuntimeFramework.MonoExePath; string monoOptions = "--runtime=v" + TargetRuntime.ClrVersion.ToString(3); monoOptions += " --debug"; StartInfo.Arguments = string.Format("{0} \"{1}\" {2}", monoOptions, AgentExePath, AgentArgs); } else if (TargetRuntime.Runtime == RuntimeType.Net) { StartInfo.FileName = AgentExePath; StartInfo.Arguments = AgentArgs.ToString(); StartInfo.LoadUserProfile = loadUserProfile; } else { StartInfo.FileName = AgentExePath; StartInfo.Arguments = AgentArgs.ToString(); } }
public bool CanCreateProcess(TestPackage package) { // Get target runtime string runtimeSetting = package.GetSetting(EnginePackageSettings.TargetRuntimeFramework, ""); var framework = RuntimeFramework.Parse(runtimeSetting).FrameworkName; return(framework.Identifier == ".NETFramework" && framework.Version.Major < 4); }
public ITestAgent GetAgent(TestPackage package) { // Target Runtime must be specified by this point string runtimeSetting = package.GetSetting(EnginePackageSettings.TargetRuntimeFramework, ""); Guard.OperationValid(runtimeSetting.Length > 0, "LaunchAgentProcess called with no runtime specified"); // If target runtime is not available, something went wrong earlier. // We list all available frameworks to use in debugging. var targetRuntime = RuntimeFramework.Parse(runtimeSetting); if (!_runtimeService.IsAvailable(targetRuntime.Id)) { string msg = $"The {targetRuntime} framework is not available.\r\nAvailable frameworks:"; foreach (var runtime in RuntimeFramework.AvailableFrameworks) { msg += $" {runtime}"; } throw new ArgumentException(msg); } var agentId = Guid.NewGuid(); var agentProcess = new AgentProcess(this, package, agentId); agentProcess.Exited += (sender, e) => OnAgentExit((Process)sender, agentId); agentProcess.Start(); log.Debug("Launched Agent process {0} - see nunit-agent_{0}.log", agentProcess.Id); log.Debug("Command line: \"{0}\" {1}", agentProcess.StartInfo.FileName, agentProcess.StartInfo.Arguments); _agentStore.AddAgent(agentId, agentProcess); log.Debug($"Waiting for agent {agentId:B} to register"); const int pollTime = 200; // Increase the timeout to give time to attach a debugger bool debug = package.GetSetting(EnginePackageSettings.DebugAgent, false) || package.GetSetting(EnginePackageSettings.PauseBeforeRun, false); int waitTime = debug ? DEBUG_TIMEOUT : NORMAL_TIMEOUT; // Wait for agent registration based on the agent actually getting processor time to avoid falling over // under process starvation. while (waitTime > agentProcess.TotalProcessorTime.TotalMilliseconds && !agentProcess.HasExited) { Thread.Sleep(pollTime); if (_agentStore.IsReady(agentId, out var agent)) { log.Debug($"Returning new agent {agentId:B}"); return(new TestAgentRemotingProxy(agent, agentId)); } } return(null); }
/// <summary> /// Returns true if the runtime framework represented by /// the string passed as an argument is available. /// </summary> /// <param name="name">A string representing a framework, like 'net-4.0'</param> /// <returns>True if the framework is available, false if unavailable or nonexistent</returns> public bool IsAvailable(string name) { var requestedFramework = RuntimeFramework.Parse(name); foreach (var framework in RuntimeFramework.AvailableFrameworks) if (FrameworksMatch(requestedFramework, framework)) return true; return false; }
/// <summary> /// Return an agent, which best matches the criteria defined /// in a TestPackage. /// </summary> /// <param name="package">The test package to be run</param> /// <returns>An ITestAgent</returns> /// <exception cref="ArgumentException">If no agent is available.</exception> public ITestAgent GetAgent(TestPackage package) { // Target Runtime must be specified by this point string runtimeSetting = package.GetSetting(EnginePackageSettings.TargetRuntimeFramework, ""); Guard.OperationValid(runtimeSetting.Length > 0, "LaunchAgentProcess called with no runtime specified"); var targetRuntime = RuntimeFramework.Parse(runtimeSetting); var agentId = Guid.NewGuid(); string agencyUrl = targetRuntime.FrameworkName.Identifier == ".NETFramework" ? RemotingUrl : TcpEndPoint; var agentProcess = CreateAgentProcess(agentId, agencyUrl, package); agentProcess.Exited += (sender, e) => OnAgentExit((Process)sender); Console.WriteLine(agentProcess.StartInfo.FileName); agentProcess.Start(); log.Debug("Launched Agent process {0} - see testcentric-agent_{0}.log", agentProcess.Id); log.Debug("Command line: \"{0}\" {1}", agentProcess.StartInfo.FileName, agentProcess.StartInfo.Arguments); _agentStore.AddAgent(agentId, agentProcess); log.Debug($"Waiting for agent {agentId:B} to register"); const int pollTime = 200; // Increase the timeout to give time to attach a debugger bool debug = package.GetSetting(EnginePackageSettings.DebugAgent, false) || package.GetSetting(EnginePackageSettings.PauseBeforeRun, false); int waitTime = debug ? DEBUG_TIMEOUT : NORMAL_TIMEOUT; // Wait for agent registration based on the agent actually getting processor time to avoid falling over // under process starvation. while (waitTime > agentProcess.TotalProcessorTime.TotalMilliseconds && !agentProcess.HasExited) { Thread.Sleep(pollTime); if (_agentStore.IsAvailable(agentId, out var agent)) { log.Debug($"Returning new agent {agentId:B}"); switch (targetRuntime.Runtime.FrameworkIdentifier) { case FrameworkIdentifiers.NetFramework: return(new TestAgentRemotingProxy(agent, agentId)); case FrameworkIdentifiers.NetCoreApp: return(agent); default: throw new InvalidOperationException($"Invalid runtime: {targetRuntime.Runtime.FrameworkIdentifier}"); } } } return(null); }
public void WellKnownClrVersions_SupportEquivalentFrameworkVersions(string s) { RuntimeFramework f1 = RuntimeFramework.Parse(s); RuntimeFramework f2 = new RuntimeFramework(f1.Runtime, f1.FrameworkVersion); Assert.That(f1.Runtime, Is.EqualTo(f2.Runtime)); Assert.That(f1.FrameworkVersion, Is.EqualTo(f2.FrameworkVersion)); Assert.That(f1.ClrVersion, Is.EqualTo(f2.ClrVersion)); Assert.That(f1.Supports(f2)); Assert.That(f2.Supports(f1)); }
/// <summary> /// Selects a target runtime framework for a TestPackage based on /// the settings in the package and the assemblies themselves. /// The package RuntimeFramework setting may be updated as a result /// and a string representing the selected runtime is returned. /// </summary> /// <param name="package">A TestPackage</param> /// <returns>A string representing the selected RuntimeFramework</returns> public string SelectRuntimeFramework(TestPackage package) { // Evaluate package target framework ApplyImageData(package); // Examine the provided settings RuntimeFramework currentFramework = RuntimeFramework.CurrentFramework; string frameworkSetting = package.GetSetting(EnginePackageSettings.RuntimeFramework, ""); RuntimeFramework requestedFramework = frameworkSetting.Length > 0 ? RuntimeFramework.Parse(frameworkSetting) : new RuntimeFramework(RuntimeType.Any, RuntimeFramework.DefaultVersion); log.Debug("Current framework is {0}", currentFramework); if (requestedFramework == null) { log.Debug("No specific framework requested"); } else { log.Debug("Requested framework is {0}", requestedFramework); } RuntimeType targetRuntime = requestedFramework.Runtime; Version targetVersion = requestedFramework.FrameworkVersion; if (targetRuntime == RuntimeType.Any) { targetRuntime = currentFramework.Runtime; } if (targetVersion == RuntimeFramework.DefaultVersion) { targetVersion = package.GetSetting(InternalEnginePackageSettings.ImageRuntimeVersion, currentFramework.FrameworkVersion); } if (!new RuntimeFramework(targetRuntime, targetVersion).IsAvailable) { log.Debug("Preferred version {0} is not installed or this NUnit installation does not support it", targetVersion); if (targetVersion < currentFramework.FrameworkVersion) { targetVersion = currentFramework.FrameworkVersion; } } RuntimeFramework targetFramework = new RuntimeFramework(targetRuntime, targetVersion); package.Settings[EnginePackageSettings.RuntimeFramework] = targetFramework.ToString(); log.Debug("Test will use {0} framework", targetFramework); return(targetFramework.ToString()); }
public void SelectRuntimeFramework(string assemblyName, string expectedVersion, bool runAsX86) { // Some files don't actually exist on our CI servers Assume.That(assemblyName, Does.Exist); var package = new TestPackage(assemblyName); var returnValue = _runtimeService.SelectRuntimeFramework(package); var framework = RuntimeFramework.Parse(returnValue); Assert.That(package.GetSetting("RuntimeFramework", ""), Is.EqualTo(returnValue)); Assert.That(package.GetSetting("RunAsX86", false), Is.EqualTo(runAsX86)); Assert.That(framework.ClrVersion.ToString(), Is.EqualTo(expectedVersion)); }
/// <summary> /// Returns true if the runtime framework represented by /// the string passed as an argument is available. /// </summary> /// <param name="name">A string representing a framework, like 'net-4.0'</param> /// <returns>True if the framework is available, false if unavailable or nonexistent</returns> public bool IsAvailable(string name) { var requestedFramework = RuntimeFramework.Parse(name); foreach (var framework in RuntimeFramework.AvailableFrameworks) { if (FrameworksMatch(requestedFramework, framework)) { return(true); } } return(false); }
public ITestAgent GetAgent(TestPackage package) { // Target Runtime must be specified by this point string runtimeSetting = package.GetSetting(EnginePackageSettings.TargetRuntimeFramework, ""); Guard.OperationValid(runtimeSetting.Length > 0, "LaunchAgentProcess called with no runtime specified"); var targetRuntime = RuntimeFramework.Parse(runtimeSetting); if (!_runtimeService.IsAvailable(targetRuntime.Id)) { throw new ArgumentException( string.Format("The {0} framework is not available", targetRuntime), "framework"); } // TODO: Decide if we should reuse agents return(CreateRemoteAgent(package, targetRuntime)); }
private Guid LaunchAgentProcess(TestPackage package) { RuntimeFramework targetRuntime = RuntimeFramework.CurrentFramework; string runtimeSetting = package.GetSetting(EnginePackageSettings.RuntimeFramework, ""); if (runtimeSetting != "") { targetRuntime = RuntimeFramework.Parse(runtimeSetting); } if (targetRuntime.Runtime == RuntimeType.Any) { targetRuntime = new RuntimeFramework(RuntimeFramework.CurrentFramework.Runtime, targetRuntime.ClrVersion); } bool useX86Agent = package.GetSetting(EnginePackageSettings.RunAsX86, false); bool debugTests = package.GetSetting(EnginePackageSettings.DebugTests, false); bool debugAgent = package.GetSetting(EnginePackageSettings.DebugAgent, false); string traceLevel = package.GetSetting(EnginePackageSettings.InternalTraceLevel, "Off"); bool loadUserProfile = package.GetSetting(EnginePackageSettings.LoadUserProfile, false); // Set options that need to be in effect before the package // is loaded by using the command line. string agentArgs = "--pid=" + Process.GetCurrentProcess().Id.ToString(); if (debugAgent) { agentArgs += " --debug-agent"; } if (traceLevel != "Off") { agentArgs += " --trace:" + traceLevel; } log.Info("Getting {0} agent for use under {1}", useX86Agent ? "x86" : "standard", targetRuntime); if (!targetRuntime.IsAvailable) { throw new ArgumentException( string.Format("The {0} framework is not available", targetRuntime), "framework"); } string agentExePath = GetTestAgentExePath(useX86Agent); if (agentExePath == null) { throw new ArgumentException( string.Format("NUnit components for version {0} of the CLR are not installed", targetRuntime.ClrVersion.ToString()), "targetRuntime"); } log.Debug("Using nunit-agent at " + agentExePath); Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = true; Guid agentId = Guid.NewGuid(); string arglist = agentId.ToString() + " " + ServerUrl + " " + agentArgs; targetRuntime = RuntimeFramework.GetBestAvailableFramework(targetRuntime); switch (targetRuntime.Runtime) { case RuntimeType.Mono: p.StartInfo.FileName = RuntimeFramework.MonoExePath; string monoOptions = "--runtime=v" + targetRuntime.ClrVersion.ToString(3); if (debugTests || debugAgent) { monoOptions += " --debug"; } p.StartInfo.Arguments = string.Format("{0} \"{1}\" {2}", monoOptions, agentExePath, arglist); break; case RuntimeType.Net: p.StartInfo.FileName = agentExePath; // Override the COMPLUS_Version env variable, this would cause CLR meta host to run a CLR of the specific version string envVar = "v" + targetRuntime.ClrVersion.ToString(3); p.StartInfo.EnvironmentVariables["COMPLUS_Version"] = envVar; // Leave a marker that we have changed this variable, so that the agent could restore it for any code or child processes running within the agent string cpvOriginal = Environment.GetEnvironmentVariable("COMPLUS_Version"); p.StartInfo.EnvironmentVariables["TestAgency_COMPLUS_Version_Original"] = string.IsNullOrEmpty(cpvOriginal) ? "NULL" : cpvOriginal; p.StartInfo.Arguments = arglist; p.StartInfo.LoadUserProfile = loadUserProfile; break; default: p.StartInfo.FileName = agentExePath; p.StartInfo.Arguments = arglist; break; } p.Start(); log.Debug("Launched Agent process {0} - see nunit-agent_{0}.log", p.Id); log.Debug("Command line: \"{0}\" {1}", p.StartInfo.FileName, p.StartInfo.Arguments); _agentData.Add(new AgentRecord(agentId, p, null, AgentStatus.Starting)); return(agentId); }
/// <summary> /// Selects a target runtime framework for a TestPackage based on /// the settings in the package and the assemblies themselves. /// The package RuntimeFramework setting may be updated as a result /// and a string representing the selected runtime is returned. /// </summary> /// <param name="package">A TestPackage</param> /// <returns>A string representing the selected RuntimeFramework</returns> public string SelectRuntimeFramework(TestPackage package) { RuntimeFramework currentFramework = RuntimeFramework.CurrentFramework; string frameworkSetting = package.GetSetting(PackageSettings.RuntimeFramework, ""); RuntimeFramework requestedFramework = frameworkSetting.Length > 0 ? RuntimeFramework.Parse(frameworkSetting) : new RuntimeFramework(RuntimeType.Any, RuntimeFramework.DefaultVersion); log.Debug("Current framework is {0}", currentFramework); if (requestedFramework == null) { log.Debug("No specific framework requested"); } else { log.Debug("Requested framework is {0}", requestedFramework); } RuntimeType targetRuntime = requestedFramework.Runtime; Version targetVersion = requestedFramework.FrameworkVersion; if (targetRuntime == RuntimeType.Any) { targetRuntime = currentFramework.Runtime; } if (targetVersion == RuntimeFramework.DefaultVersion) { var packages = package.SubPackages; if (packages.Count == 0) { packages.Add(package); } foreach (var subPackage in packages) { var assembly = subPackage.FullName; // If the file is not an assembly or doesn't exist, then it can't // contribute any information to the decision, so we skip it. if (PathUtils.IsAssemblyFileType(assembly) && File.Exists(assembly)) { var module = AssemblyDefinition.ReadAssembly(assembly).MainModule; var NativeEntryPoint = (ModuleAttributes)16; var mask = ModuleAttributes.Required32Bit | NativeEntryPoint; if (module.Architecture != TargetArchitecture.AMD64 && module.Architecture != TargetArchitecture.IA64 && (module.Attributes & mask) != 0) { package.Settings[PackageSettings.RunAsX86] = true; log.Debug("Assembly {0} will be run x86", assembly); } var v = new Version(module.RuntimeVersion.Substring(1)); log.Debug("Assembly {0} uses version {1}", assembly, v); // TODO: We are doing two jobs here: (1) getting the // target version and (2) applying a policy that says // we run under the highest version of all assemblies. // We should implement the policy at a higher level. if (v > targetVersion) { targetVersion = v; } } } RuntimeFramework checkFramework = new RuntimeFramework(targetRuntime, targetVersion); if (!checkFramework.IsAvailable) { log.Debug("Preferred version {0} is not installed or this NUnit installation does not support it", targetVersion); if (targetVersion < currentFramework.FrameworkVersion) { targetVersion = currentFramework.FrameworkVersion; } } } RuntimeFramework targetFramework = new RuntimeFramework(targetRuntime, targetVersion); package.Settings[PackageSettings.RuntimeFramework] = targetFramework.ToString(); log.Debug("Test will use {0} framework", targetFramework); return(targetFramework.ToString()); }
//public void DestroyAgent( ITestAgent agent ) //{ // AgentRecord r = agentData[agent.Id]; // if ( r != null ) // { // if( !r.Process.HasExited ) // r.Agent.Stop(); // agentData[r.Id] = null; // } //} #endregion #region Helper Methods private Guid LaunchAgentProcess(TestPackage package) { string runtimeSetting = package.GetSetting(PackageSettings.RuntimeFramework, ""); RuntimeFramework targetRuntime = RuntimeFramework.Parse( runtimeSetting != "" ? runtimeSetting : ServiceContext.RuntimeFrameworkService.SelectRuntimeFramework(package)); bool useX86Agent = package.GetSetting(PackageSettings.RunAsX86, false); bool enableDebug = package.GetSetting("AgentDebug", false); bool verbose = package.GetSetting("Verbose", false); string agentArgs = string.Empty; if (enableDebug) { agentArgs += " --pause"; } if (verbose) { agentArgs += " --verbose"; } log.Info("Getting {0} agent for use under {1}", useX86Agent ? "x86" : "standard", targetRuntime); if (!targetRuntime.IsAvailable) { throw new ArgumentException( string.Format("The {0} framework is not available", targetRuntime), "framework"); } string agentExePath = GetTestAgentExePath(targetRuntime.ClrVersion, useX86Agent); if (agentExePath == null) { throw new ArgumentException( string.Format("NUnit components for version {0} of the CLR are not installed", targetRuntime.ClrVersion.ToString()), "targetRuntime"); } log.Debug("Using nunit-agent at " + agentExePath); Process p = new Process(); p.StartInfo.UseShellExecute = false; Guid agentId = Guid.NewGuid(); string arglist = agentId.ToString() + " " + ServerUrl + " " + agentArgs; switch (targetRuntime.Runtime) { case RuntimeType.Mono: p.StartInfo.FileName = NUnitConfiguration.MonoExePath; string monoOptions = "--runtime=v" + targetRuntime.ClrVersion.ToString(3); if (enableDebug) { monoOptions += " --debug"; } p.StartInfo.Arguments = string.Format("{0} \"{1}\" {2}", monoOptions, agentExePath, arglist); break; case RuntimeType.Net: p.StartInfo.FileName = agentExePath; if (targetRuntime.ClrVersion.Build < 0) { targetRuntime = RuntimeFramework.GetBestAvailableFramework(targetRuntime); } string envVar = "v" + targetRuntime.ClrVersion.ToString(3); p.StartInfo.EnvironmentVariables["COMPLUS_Version"] = envVar; p.StartInfo.Arguments = arglist; break; default: p.StartInfo.FileName = agentExePath; p.StartInfo.Arguments = arglist; break; } //p.Exited += new EventHandler(OnProcessExit); p.Start(); log.Info("Launched Agent process {0} - see nunit-agent_{0}.log", p.Id); log.Info("Command line: \"{0}\" {1}", p.StartInfo.FileName, p.StartInfo.Arguments); agentData.Add(new AgentRecord(agentId, p, null, AgentStatus.Starting)); return(agentId); }
private Process LaunchAgentProcess(TestPackage package, Guid agentId) { string runtimeSetting = package.GetSetting(EnginePackageSettings.RuntimeFramework, ""); // TEMPORARY Guard in preparation for removing Runtime.Any Guard.OperationValid(runtimeSetting.Length > 0, "LaunchAgentProcess called with no runtime specified"); var targetRuntime = RuntimeFramework.Parse(runtimeSetting); bool useX86Agent = package.GetSetting(EnginePackageSettings.RunAsX86, false); bool debugTests = package.GetSetting(EnginePackageSettings.DebugTests, false); bool debugAgent = package.GetSetting(EnginePackageSettings.DebugAgent, false); string traceLevel = package.GetSetting(EnginePackageSettings.InternalTraceLevel, "Off"); bool loadUserProfile = package.GetSetting(EnginePackageSettings.LoadUserProfile, false); string workDirectory = package.GetSetting(EnginePackageSettings.WorkDirectory, string.Empty); var agentArgs = new StringBuilder(); // Set options that need to be in effect before the package // is loaded by using the command line. agentArgs.Append("--pid=").Append(Process.GetCurrentProcess().Id); if (traceLevel != "Off") { agentArgs.Append(" --trace:").EscapeProcessArgument(traceLevel); } if (debugAgent) { agentArgs.Append(" --debug-agent"); } if (workDirectory != string.Empty) { agentArgs.Append(" --work=").EscapeProcessArgument(workDirectory); } log.Info("Getting {0} agent for use under {1}", useX86Agent ? "x86" : "standard", targetRuntime); if (!_runtimeService.IsAvailable(targetRuntime.Id)) { throw new ArgumentException( string.Format("The {0} framework is not available", targetRuntime), "framework"); } string agentExePath = GetTestAgentExePath(useX86Agent); if (!File.Exists(agentExePath)) { throw new FileNotFoundException( $"{Path.GetFileName(agentExePath)} could not be found.", agentExePath); } log.Debug("Using testcentric-agent at " + agentExePath); Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = true; p.EnableRaisingEvents = true; p.Exited += (sender, e) => OnAgentExit((Process)sender, agentId); string arglist = agentId.ToString() + " " + ServerUrl + " " + agentArgs; targetRuntime = ServiceContext.GetService <RuntimeFrameworkService>().GetBestAvailableFramework(targetRuntime); if (targetRuntime.Runtime == Runtime.Mono) { p.StartInfo.FileName = targetRuntime.MonoExePath; string monoOptions = "--runtime=v" + targetRuntime.ClrVersion.ToString(3); if (debugTests || debugAgent) { monoOptions += " --debug"; } p.StartInfo.Arguments = string.Format("{0} \"{1}\" {2}", monoOptions, agentExePath, arglist); } else if (targetRuntime.Runtime == Runtime.Net) { p.StartInfo.FileName = agentExePath; // Override the COMPLUS_Version env variable, this would cause CLR meta host to run a CLR of the specific version string envVar = "v" + targetRuntime.ClrVersion.ToString(3); p.StartInfo.EnvironmentVariables["COMPLUS_Version"] = envVar; // Leave a marker that we have changed this variable, so that the agent could restore it for any code or child processes running within the agent string cpvOriginal = Environment.GetEnvironmentVariable("COMPLUS_Version"); p.StartInfo.EnvironmentVariables["TestAgency_COMPLUS_Version_Original"] = string.IsNullOrEmpty(cpvOriginal) ? "NULL" : cpvOriginal; p.StartInfo.Arguments = arglist; p.StartInfo.LoadUserProfile = loadUserProfile; } else { p.StartInfo.FileName = agentExePath; p.StartInfo.Arguments = arglist; } p.Start(); log.Debug("Launched Agent process {0} - see testcentric-agent_{0}.log", p.Id); log.Debug("Command line: \"{0}\" {1}", p.StartInfo.FileName, p.StartInfo.Arguments); _agents.Start(agentId, p); return(p); }
// TODO: See if this can be unified with the Gui's MakeTestPackage private static TestPackage MakeTestPackage(ConsoleOptions options) { TestPackage package; DomainUsage domainUsage = DomainUsage.Default; ProcessModel processModel = ProcessModel.Default; RuntimeFramework framework = null; if (options.IsTestProject) { NUnitProject project = Services.ProjectService.LoadProject((string)options.Parameters[0]); string configName = options.config; if (configName != null) { project.SetActiveConfig(configName); } package = project.ActiveConfig.MakeTestPackage(); processModel = project.ProcessModel; domainUsage = project.DomainUsage; framework = project.ActiveConfig.RuntimeFramework; } else if (options.Parameters.Count == 1) { package = new TestPackage((string)options.Parameters[0]); domainUsage = DomainUsage.Single; } else { // TODO: Figure out a better way to handle "anonymous" packages package = new TestPackage(null, options.Parameters); package.AutoBinPath = true; domainUsage = DomainUsage.Multiple; } if (options.process != ProcessModel.Default) { processModel = options.process; } if (options.domain != DomainUsage.Default) { domainUsage = options.domain; } if (options.framework != null) { framework = RuntimeFramework.Parse(options.framework); } package.TestName = options.fixture; package.Settings["ProcessModel"] = processModel; package.Settings["DomainUsage"] = domainUsage; if (framework != null) { package.Settings["RuntimeFramework"] = framework; } if (domainUsage == DomainUsage.None) { // Make sure that addins are available CoreExtensions.Host.AddinRegistry = Services.AddinRegistry; } package.Settings["ShadowCopyFiles"] = !options.noshadow; package.Settings["UseThreadedRunner"] = !options.nothread; package.Settings["DefaultTimeout"] = options.timeout; return(package); }
/// <summary> /// Selects a target runtime framework for a TestPackage based on /// the settings in the package and the assemblies themselves. /// The package RuntimeFramework setting may be updated as a result /// and a string representing the selected runtime is returned. /// </summary> /// <param name="package">A TestPackage</param> /// <returns>A string representing the selected RuntimeFramework</returns> public string SelectRuntimeFramework(TestPackage package) { RuntimeFramework currentFramework = RuntimeFramework.CurrentFramework; string frameworkSetting = package.GetSetting(PackageSettings.RuntimeFramework, ""); RuntimeFramework requestedFramework = frameworkSetting.Length > 0 ? RuntimeFramework.Parse(frameworkSetting) : new RuntimeFramework(RuntimeType.Any, RuntimeFramework.DefaultVersion); log.Debug("Current framework is {0}", currentFramework); if (requestedFramework == null) { log.Debug("No specific framework requested"); } else { log.Debug("Requested framework is {0}", requestedFramework); } RuntimeType targetRuntime = requestedFramework.Runtime; Version targetVersion = requestedFramework.FrameworkVersion; if (targetRuntime == RuntimeType.Any) { targetRuntime = currentFramework.Runtime; } if (targetVersion == RuntimeFramework.DefaultVersion) { if (ServiceContext.UserSettings.GetSetting("Options.TestLoader.RuntimeSelectionEnabled", true)) { foreach (string assembly in package.TestFiles) { // If the file is not an assembly or doesn't exist, then it can't // contribute any information to the decision, so we skip it. if (PathUtils.IsAssemblyFileType(assembly) && File.Exists(assembly)) { using (var reader = new AssemblyReader(assembly)) { if (!reader.IsValidPeFile) { log.Debug("{0} is not a valid PE file", assembly); } else if (!reader.IsDotNetFile) { log.Debug("{0} is not a managed assembly", assembly); } else { if (reader.ShouldRun32Bit) { package.Settings[PackageSettings.RunAsX86] = true; log.Debug("Assembly {0} will be run x86", assembly); } var imageRuntimeVersion = reader.ImageRuntimeVersion; if (imageRuntimeVersion != null) { var v = new Version(imageRuntimeVersion.Substring(1)); log.Debug("Assembly {0} uses version {1}", assembly, v); // TODO: We are doing two jobs here: (1) getting the // target version and (2) applying a policy that says // we run under the highest version of all assemblies. // We should implement the policy at a higher level. if (v > targetVersion) { targetVersion = v; } } } } } } } else { targetVersion = RuntimeFramework.CurrentFramework.ClrVersion; } RuntimeFramework checkFramework = new RuntimeFramework(targetRuntime, targetVersion); if (!checkFramework.IsAvailable || !ServiceContext.TestAgency.IsRuntimeVersionSupported(targetVersion)) { log.Debug("Preferred version {0} is not installed or this NUnit installation does not support it", targetVersion); if (targetVersion < currentFramework.FrameworkVersion) { targetVersion = currentFramework.FrameworkVersion; } } } RuntimeFramework targetFramework = new RuntimeFramework(targetRuntime, targetVersion); package.Settings[PackageSettings.RuntimeFramework] = targetFramework.ToString(); log.Debug("Test will use {0} framework", targetFramework); return(targetFramework.ToString()); }
/// <summary> /// Selects a target runtime framework for a TestPackage based on /// the settings in the package and the assemblies themselves. /// The package RuntimeFramework setting may be updated as a /// result and the selected runtime is returned. /// </summary> /// <param name="package">A TestPackage</param> /// <returns>The selected RuntimeFramework</returns> public RuntimeFramework SelectRuntimeFramework(TestPackage package) { RuntimeFramework currentFramework = RuntimeFramework.CurrentFramework; string frameworkSetting = package.GetSetting(RunnerSettings.RuntimeFramework, ""); RuntimeFramework requestedFramework = frameworkSetting.Length > 0 ? RuntimeFramework.Parse(frameworkSetting) : new RuntimeFramework(RuntimeType.Any, RuntimeFramework.DefaultVersion); log.Debug("Current framework is {0}", currentFramework); if (requestedFramework == null) { log.Debug("No specific framework requested"); } else { log.Debug("Requested framework is {0}", requestedFramework); } RuntimeType targetRuntime = requestedFramework.Runtime; Version targetVersion = requestedFramework.FrameworkVersion; if (targetRuntime == RuntimeType.Any) { targetRuntime = currentFramework.Runtime; } if (targetVersion == RuntimeFramework.DefaultVersion) { if (ServiceContext.UserSettings.GetSetting("Options.TestLoader.RuntimeSelectionEnabled", true)) { foreach (string assembly in package.TestFiles) { using (AssemblyReader reader = new AssemblyReader(assembly)) { Version v = new Version(reader.ImageRuntimeVersion.Substring(1)); log.Debug("Assembly {0} uses version {1}", assembly, v); if (v > targetVersion) { targetVersion = v; } } } } else { targetVersion = RuntimeFramework.CurrentFramework.ClrVersion; } RuntimeFramework checkFramework = new RuntimeFramework(targetRuntime, targetVersion); if (!checkFramework.IsAvailable || !ServiceContext.TestAgency.IsRuntimeVersionSupported(targetVersion)) { log.Debug("Preferred version {0} is not installed or this NUnit installation does not support it", targetVersion); if (targetVersion < currentFramework.FrameworkVersion) { targetVersion = currentFramework.FrameworkVersion; } } } RuntimeFramework targetFramework = new RuntimeFramework(targetRuntime, targetVersion); package.Settings[RunnerSettings.RuntimeFramework] = targetFramework.ToString(); log.Debug("Test will use {0} framework", targetFramework); return(targetFramework); }
private RuntimeFramework Framework(string representation) { return(RuntimeFramework.Parse(representation)); }
public void Load() { XmlTextReader reader = new XmlTextReader(projectPath); string activeConfigName = null; ProjectConfig currentConfig = null; try { reader.MoveToContent(); if (reader.NodeType != XmlNodeType.Element || reader.Name != "NUnitProject") { throw new ProjectFormatException( "Invalid project format: <NUnitProject> expected.", reader.LineNumber, reader.LinePosition); } while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { switch (reader.Name) { case "Settings": if (reader.NodeType == XmlNodeType.Element) { activeConfigName = reader.GetAttribute("activeconfig"); string autoConfig = reader.GetAttribute("autoconfig"); if (autoConfig != null) { this.AutoConfig = autoConfig.ToLower() == "true"; } if (this.AutoConfig) { activeConfigName = NUnitConfiguration.BuildConfiguration; } string appbase = reader.GetAttribute("appbase"); if (appbase != null) { this.BasePath = appbase; } string processModel = reader.GetAttribute("processModel"); if (processModel != null) { this.ProcessModel = (ProcessModel)Enum.Parse(typeof(ProcessModel), processModel); } string domainUsage = reader.GetAttribute("domainUsage"); if (domainUsage != null) { this.DomainUsage = (DomainUsage)Enum.Parse(typeof(DomainUsage), domainUsage); } } break; case "Config": if (reader.NodeType == XmlNodeType.Element) { string configName = reader.GetAttribute("name"); currentConfig = new ProjectConfig(configName); currentConfig.BasePath = reader.GetAttribute("appbase"); currentConfig.ConfigurationFile = reader.GetAttribute("configfile"); string binpath = reader.GetAttribute("binpath"); currentConfig.PrivateBinPath = binpath; string type = reader.GetAttribute("binpathtype"); if (type == null) { if (binpath == null) { currentConfig.BinPathType = BinPathType.Auto; } else { currentConfig.BinPathType = BinPathType.Manual; } } else { currentConfig.BinPathType = (BinPathType)Enum.Parse(typeof(BinPathType), type, true); } string runtime = reader.GetAttribute("runtimeFramework"); if (runtime != null) { currentConfig.RuntimeFramework = RuntimeFramework.Parse(runtime); } Configs.Add(currentConfig); if (configName == activeConfigName) { activeConfig = currentConfig; } } else if (reader.NodeType == XmlNodeType.EndElement) { currentConfig = null; } break; case "assembly": if (reader.NodeType == XmlNodeType.Element && currentConfig != null) { string path = reader.GetAttribute("path"); currentConfig.Assemblies.Add( Path.Combine(currentConfig.BasePath, path)); } break; default: break; } } } this.IsDirty = false; this.reloadRequired = false; } catch (FileNotFoundException) { throw; } catch (XmlException e) { throw new ProjectFormatException( string.Format("Invalid project format: {0}", e.Message), e.LineNumber, e.LinePosition); } catch (Exception e) { throw new ProjectFormatException( string.Format("Invalid project format: {0} Line {1}, Position {2}", e.Message, reader.LineNumber, reader.LinePosition), reader.LineNumber, reader.LinePosition); } finally { reader.Close(); } }
public AgentProcess(TestAgency agency, TestPackage package, Guid agentId) { // Get target runtime string runtimeSetting = package.GetSetting(EnginePackageSettings.TargetRuntimeFramework, ""); log.Debug($"TargetRuntime = {runtimeSetting}"); TargetRuntime = RuntimeFramework.Parse(runtimeSetting); // Access other package settings bool runAsX86 = package.GetSetting(EnginePackageSettings.RunAsX86, false); bool debugAgent = package.GetSetting(EnginePackageSettings.DebugAgent, false); string traceLevel = package.GetSetting(EnginePackageSettings.InternalTraceLevel, "Off"); bool loadUserProfile = package.GetSetting(EnginePackageSettings.LoadUserProfile, false); string workDirectory = package.GetSetting(EnginePackageSettings.WorkDirectory, string.Empty); string agencyUrl = TargetRuntime.Runtime == RuntimeType.NetCore ? agency.TcpEndPoint : agency.RemotingUrl; AgentArgs = new StringBuilder($"{agentId} {agencyUrl} --pid={Process.GetCurrentProcess().Id}"); // Set options that need to be in effect before the package // is loaded by using the command line. if (traceLevel != "Off") { AgentArgs.Append(" --trace=").EscapeProcessArgument(traceLevel); } if (debugAgent) { AgentArgs.Append(" --debug-agent"); } if (workDirectory != string.Empty) { AgentArgs.Append(" --work=").EscapeProcessArgument(workDirectory); } AgentExePath = GetTestAgentExePath(TargetRuntime, runAsX86); log.Debug("Using nunit-agent at " + AgentExePath); StartInfo.UseShellExecute = false; StartInfo.CreateNoWindow = true; StartInfo.WorkingDirectory = Environment.CurrentDirectory; EnableRaisingEvents = true; if (TargetRuntime.Runtime == RuntimeType.Mono) { StartInfo.FileName = RuntimeFramework.MonoExePath; string monoOptions = "--runtime=v" + TargetRuntime.ClrVersion.ToString(3); monoOptions += " --debug"; StartInfo.Arguments = string.Format("{0} \"{1}\" {2}", monoOptions, AgentExePath, AgentArgs); } else if (TargetRuntime.Runtime == RuntimeType.Net) { StartInfo.FileName = AgentExePath; StartInfo.Arguments = AgentArgs.ToString(); StartInfo.LoadUserProfile = loadUserProfile; } else if (TargetRuntime.Runtime == RuntimeType.NetCore) { StartInfo.FileName = "dotnet"; StartInfo.Arguments = $"{AgentExePath} {AgentArgs}"; StartInfo.LoadUserProfile = loadUserProfile; // TODO: Remove the windows limitation and the use of a hard-coded path. if (runAsX86) { if (Path.DirectorySeparatorChar != '\\') { throw new Exception("Running .NET Core as X86 is currently only supported on Windows"); } var x86_dotnet_exe = @"C:\Program Files (x86)\dotnet\dotnet.exe"; if (!File.Exists(x86_dotnet_exe)) { throw new Exception("The X86 version of dotnet.exe is not installed"); } StartInfo.FileName = x86_dotnet_exe; } } else { StartInfo.FileName = AgentExePath; StartInfo.Arguments = AgentArgs.ToString(); } }
// TODO: See if this can be unified with the Gui's MakeTestPackage private TestPackage MakeTestPackage(ConsoleOptions options) { TestPackage package; DomainUsage domainUsage = DomainUsage.Default; ProcessModel processModel = ProcessModel.Default; RuntimeFramework framework = null; string[] parameters = new string[options.ParameterCount]; for (int i = 0; i < options.ParameterCount; i++) { parameters[i] = Path.GetFullPath((string)options.Parameters[i]); } if (options.IsTestProject) { NUnitProject project = Services.ProjectService.LoadProject(parameters[0]); string configName = options.config; if (configName != null) { project.SetActiveConfig(configName); } package = project.ActiveConfig.MakeTestPackage(); processModel = project.ProcessModel; domainUsage = project.DomainUsage; framework = project.ActiveConfig.RuntimeFramework; } else if (parameters.Length == 1) { package = new TestPackage(parameters[0]); domainUsage = DomainUsage.Single; } else { // TODO: Figure out a better way to handle "anonymous" packages package = new TestPackage(null, parameters); package.AutoBinPath = true; domainUsage = DomainUsage.Multiple; } #if CLR_2_0 || CLR_4_0 if (options.framework != null) { framework = RuntimeFramework.Parse(options.framework); } if (options.process != ProcessModel.Default) { processModel = options.process; } #endif if (options.domain != DomainUsage.Default) { domainUsage = options.domain; } package.TestName = options.fixture; package.Settings["ProcessModel"] = processModel; package.Settings["DomainUsage"] = domainUsage; if (framework != null) { package.Settings["RuntimeFramework"] = framework; } if (domainUsage == DomainUsage.None) { // Make sure that addins are available CoreExtensions.Host.AddinRegistry = Services.AddinRegistry; } package.Settings["ShadowCopyFiles"] = !options.noshadow; package.Settings["UseThreadedRunner"] = !options.nothread; package.Settings["DefaultTimeout"] = options.timeout; package.Settings["WorkDirectory"] = this.workDir; package.Settings["StopOnError"] = options.stoponerror; if (options.apartment != System.Threading.ApartmentState.Unknown) { package.Settings["ApartmentState"] = options.apartment; } return(package); }
//public void DestroyAgent( ITestAgent agent ) //{ // AgentRecord r = agentData[agent.Id]; // if ( r != null ) // { // if( !r.Process.HasExited ) // r.Agent.Stop(); // agentData[r.Id] = null; // } //} #endregion #region Helper Methods private Guid LaunchAgentProcess(TestPackage package) { RuntimeFramework targetRuntime = RuntimeFramework.CurrentFramework; string runtimeSetting = package.GetSetting(PackageSettings.RuntimeFramework, ""); if (runtimeSetting != "") { targetRuntime = RuntimeFramework.Parse(runtimeSetting); } if (targetRuntime.Runtime == RuntimeType.Any) { targetRuntime = new RuntimeFramework(RuntimeFramework.CurrentFramework.Runtime, targetRuntime.ClrVersion); } bool useX86Agent = package.GetSetting(PackageSettings.RunAsX86, false); bool debugTests = package.GetSetting(PackageSettings.DebugTests, false); bool debugAgent = package.GetSetting(PackageSettings.DebugAgent, false); string traceLevel = package.GetSetting(PackageSettings.InternalTraceLevel, "Off"); // Set options that need to be in effect before the package // is loaded by using the command line. string agentArgs = string.Empty; if (debugAgent) { agentArgs += " --debug-agent"; } if (traceLevel != "Off") { agentArgs += " --trace:" + traceLevel; } log.Info("Getting {0} agent for use under {1}", useX86Agent ? "x86" : "standard", targetRuntime); if (!targetRuntime.IsAvailable) { throw new ArgumentException( string.Format("The {0} framework is not available", targetRuntime), "framework"); } string agentExePath = GetTestAgentExePath(targetRuntime.ClrVersion, useX86Agent); if (agentExePath == null) { throw new ArgumentException( string.Format("NUnit components for version {0} of the CLR are not installed", targetRuntime.ClrVersion.ToString()), "targetRuntime"); } log.Debug("Using nunit-agent at " + agentExePath); Process p = new Process(); p.StartInfo.UseShellExecute = false; Guid agentId = Guid.NewGuid(); string arglist = agentId.ToString() + " " + ServerUrl + " " + agentArgs; if (targetRuntime.ClrVersion.Build < 0) { targetRuntime = RuntimeFramework.GetBestAvailableFramework(targetRuntime); } switch (targetRuntime.Runtime) { case RuntimeType.Mono: p.StartInfo.FileName = NUnitConfiguration.MonoExePath; string monoOptions = "--runtime=v" + targetRuntime.ClrVersion.ToString(3); if (debugTests || debugAgent) { monoOptions += " --debug"; } p.StartInfo.Arguments = string.Format("{0} \"{1}\" {2}", monoOptions, agentExePath, arglist); break; case RuntimeType.Net: p.StartInfo.FileName = agentExePath; string envVar = "v" + targetRuntime.ClrVersion.ToString(3); p.StartInfo.EnvironmentVariables["COMPLUS_Version"] = envVar; p.StartInfo.Arguments = arglist; break; default: p.StartInfo.FileName = agentExePath; p.StartInfo.Arguments = arglist; break; } //p.Exited += new EventHandler(OnProcessExit); p.Start(); log.Info("Launched Agent process {0} - see nunit-agent_{0}.log", p.Id); log.Info("Command line: \"{0}\" {1}", p.StartInfo.FileName, p.StartInfo.Arguments); _agentData.Add(new AgentRecord(agentId, p, null, AgentStatus.Starting)); return(agentId); }