/// <summary> /// Initializes a new instance of the <see cref="TestDeployment"/> class. Used for unit tests. /// </summary> /// <param name="deploymentItemUtility"> The deployment item utility. </param> /// <param name="deploymentUtility"> The deployment utility. </param> /// <param name="fileUtility"> The file utility. </param> internal TestDeployment(DeploymentItemUtility deploymentItemUtility, DeploymentUtility deploymentUtility, FileUtility fileUtility) { this.deploymentItemUtility = deploymentItemUtility; this.deploymentUtility = deploymentUtility; this.fileUtility = fileUtility; this.adapterSettings = null; RunDirectories = null; }
private void AppDomainCreationDisabledInRunSettings() { if (this.runSettings != null && MSTestAdapterSettings.IsAppDomainCreationDisabled(this.runSettings.SettingsXml)) { this.isAppDomainCreationDisabled = true; } this.isAppDomainCreationDisabled = false; }
internal TestSourceHost(string sourceFileName, IRunSettings runSettings, IFrameworkHandle frameworkHandle, IAppDomain appDomain) { this.sourceFileName = sourceFileName; this.runSettings = runSettings; this.frameworkHandle = frameworkHandle; this.appDomain = appDomain; // Set the environment context. this.SetContext(sourceFileName); // Set isAppDomainCreationDisabled flag this.isAppDomainCreationDisabled = (this.runSettings != null) && MSTestAdapterSettings.IsAppDomainCreationDisabled(this.runSettings.SettingsXml); }
/// <summary> /// Creates an instance of a given type in the test source host. /// </summary> /// <param name="type"> The type that needs to be created in the host. </param> /// <param name="args">The arguments to pass to the constructor. /// This array of arguments must match in number, order, and type the parameters of the constructor to invoke. /// Pass in null for a constructor with no arguments. /// </param> /// <returns> An instance of the type created in the host. </returns> /// <remarks> If a type is to be created in isolation then it needs to be a MarshalByRefObject. </remarks> public object CreateInstanceForType(Type type, object[] args) { // Honour DisableAppDomain setting if it is present in runsettings if (this.runSettings != null && MSTestAdapterSettings.IsAppDomainCreationDisabled(this.runSettings.SettingsXml)) { return(Activator.CreateInstance(type, args)); } return(AppDomainUtilities.CreateInstance( this.domain, type, args)); }
/// <summary> /// Deploy files related to the list of tests specified. /// </summary> /// <param name="tests"> The tests. </param> /// <param name="runContext"> The run context. </param> /// <param name="frameworkHandle"> The framework handle. </param> /// <returns> Return true if deployment is done. </returns> public bool Deploy(IEnumerable <TestCase> tests, IRunContext runContext, IFrameworkHandle frameworkHandle) { Debug.Assert(tests != null, "tests"); // Reset runDirectories before doing deployment, so that older values of runDirectories is not picked // even if test host is kept alive. RunDirectories = null; this.adapterSettings = MSTestSettingsProvider.Settings; bool canDeploy = this.CanDeploy(); var hasDeploymentItems = tests.Any(test => this.deploymentItemUtility.HasDeploymentItems(test)); // deployment directories should not be created in this case,simply return if (!canDeploy && hasDeploymentItems) { return(false); } RunDirectories = this.deploymentUtility.CreateDeploymentDirectories(runContext); // Deployment directories are created but deployment will not happen. // This is added just to keep consistency with MSTestv1 behavior. if (!hasDeploymentItems) { return(false); } // Object model currently does not have support for SuspendCodeCoverage. We can remove this once support is added #if !NETSTANDARD1_5 && !NET5_0 using (new SuspendCodeCoverage()) #endif { // Group the tests by source var testsBySource = from test in tests group test by test.Source into testGroup select new { Source = testGroup.Key, Tests = testGroup }; var runDirectories = RunDirectories; foreach (var group in testsBySource) { // do the deployment this.deploymentUtility.Deploy(@group.Tests, @group.Source, runContext, frameworkHandle, RunDirectories); } // Update the runDirectories RunDirectories = runDirectories; } return(true); }
private void AddSearchDirectoriesSpecifiedInRunSettingsToAssemblyResolver(AssemblyResolver assemblyResolver, string baseDirectory) { // Check if user specified any adapter settings MSTestAdapterSettings adapterSettings = MSTestSettingsProvider.Settings; if (adapterSettings != null) { try { var additionalSearchDirectories = adapterSettings.GetDirectoryListWithRecursiveProperty(baseDirectory); if (additionalSearchDirectories?.Count > 0) { assemblyResolver.AddSearchDirectoriesFromRunSetting(additionalSearchDirectories); } } catch (Exception exception) { EqtTrace.Error( "DesktopTestSourceHost.AddSearchDirectoriesSpecifiedInRunSettingsToAssemblyResolver(): Exception hit while trying to set assembly resolver for domain. Exception : {0} \n Message : {1}", exception, exception.Message); } } }
/// <summary> /// Reset the settings to its default. /// Used for testing purposes. /// </summary> internal static void Reset() { settings = null; }
/// <summary> /// Load the settings from the reader. /// </summary> /// <param name="reader">Reader to load the settings from.</param> public void Load(XmlReader reader) { ValidateArg.NotNull <XmlReader>(reader, "reader"); settings = MSTestAdapterSettings.ToSettings(reader); }
public static MSTestAdapterSettings ToSettings(XmlReader reader) { ValidateArg.NotNull <XmlReader>(reader, "reader"); // Expected format of the xml is: - // // <MSTestV2> // <DeploymentEnabled>true</DeploymentEnabled> // <DeleteDeploymentDirectoryAfterTestRunIsComplete>true</DeleteDeploymentDirectoryAfterTestRunIsComplete> // <AssemblyResolution> // <Directory path= "% HOMEDRIVE %\direvtory "includeSubDirectories = "true" /> // <Directory path= "C:\windows" includeSubDirectories = "false" /> // <Directory path= ".\DirectoryName" /> ...// by default includeSubDirectories is false // </AssemblyResolution> // </MSTestV2> MSTestAdapterSettings settings = MSTestSettingsProvider.Settings; if (!reader.IsEmptyElement) { reader.Read(); while (reader.NodeType == XmlNodeType.Element) { bool result; string elementName = reader.Name.ToUpperInvariant(); switch (elementName) { case "ASSEMBLYRESOLUTION": { settings.ReadAssemblyResolutionPath(reader); break; } case "DEPLOYMENTENABLED": { if (bool.TryParse(reader.ReadInnerXml(), out result)) { settings.DeploymentEnabled = result; } break; } case "DELETEDEPLOYMENTDIRECTORYAFTERTESTRUNISCOMPLETE": { if (bool.TryParse(reader.ReadInnerXml(), out result)) { settings.DeleteDeploymentDirectoryAfterTestRunIsComplete = result; } break; } default: { reader.Skip(); break; } } } } return(settings); }
/// <summary> /// Reset the settings to its default. /// </summary> public static void Reset() { settings = null; }
/// <summary> /// Setup the isolation host. /// </summary> public void SetupHost() { List <string> resolutionPaths = this.GetResolutionPaths(this.sourceFileName, VSInstallationUtilities.IsCurrentProcessRunningInPortableMode()); // Check if user specified any runsettings MSTestAdapterSettings adapterSettings = MSTestSettingsProvider.Settings; if (resolutionPaths != null && resolutionPaths.Count > 0) { if (EqtTrace.IsInfoEnabled) { EqtTrace.Info("TestSourceHost: Creating assembly resolver with resolution paths {0}.", string.Join(",", resolutionPaths.ToArray())); } // Adding adapter folder to resolution paths if (!resolutionPaths.Contains(Path.GetDirectoryName(typeof(TestSourceHost).Assembly.Location))) { resolutionPaths.Add(Path.GetDirectoryName(typeof(TestSourceHost).Assembly.Location)); } // Adding extensions folder to resolution paths if (!resolutionPaths.Contains(Path.GetDirectoryName(typeof(AssemblyHelper).Assembly.Location))) { resolutionPaths.Add(Path.GetDirectoryName(typeof(AssemblyHelper).Assembly.Location)); } } // Honour DisableAppDomain setting if it is present in runsettings if (this.runSettings != null && MSTestAdapterSettings.IsAppDomainCreationDisabled(this.runSettings.SettingsXml)) { if (adapterSettings != null) { try { this.assemblyResolver = new AssemblyResolver(resolutionPaths); this.assemblyResolver.AddSearchDirectoriesFromRunSetting(adapterSettings.GetDirectoryListWithRecursiveProperty(null)); } catch (Exception exception) { if (EqtTrace.IsErrorEnabled) { EqtTrace.Error(exception); } } } } var appDomainSetup = new AppDomainSetup(); // The below logic of preferential setting the appdomains appbase is needed because: // 1. We set this to the location of the test source if it is built for Full CLR -> Ideally this needs to be done in all situations. // 2. We set this to the location where the current adapter is being picked up from for UWP and .Net Core scenarios -> This needs to be // different especially for UWP because we use the desktop adapter(from %temp%\VisualStudioTestExplorerExtensions) itself for test discovery // in IDE scenarios. If the app base is set to the test source location, discovery will not work because we drop the // UWP platform service assembly at the test source location and since CLR starts looking for assemblies from the app base location, // there would be a mismatch of platform service assemblies during discovery. var frameworkVersionString = this.GetTargetFrameworkVersionString(this.sourceFileName); if (frameworkVersionString.Contains(PlatformServices.Constants.DotNetFrameWorkStringPrefix)) { appDomainSetup.ApplicationBase = Path.GetDirectoryName(this.sourceFileName) ?? Path.GetDirectoryName(typeof(TestSourceHost).Assembly.Location); } else { appDomainSetup.ApplicationBase = Path.GetDirectoryName(typeof(TestSourceHost).Assembly.Location); } if (EqtTrace.IsInfoEnabled) { EqtTrace.Info("TestSourceHost: Creating app-domain for source {0} with application base path {1}.", this.sourceFileName, appDomainSetup.ApplicationBase); } AppDomainUtilities.SetAppDomainFrameworkVersionBasedOnTestSource(appDomainSetup, frameworkVersionString); var configFile = this.GetConfigFileForTestSource(this.sourceFileName); AppDomainUtilities.SetConfigurationFile(appDomainSetup, configFile); this.domain = this.appDomain.CreateDomain("TestSourceHost: Enumering assembly", null, appDomainSetup); // Load objectModel before creating assembly resolver otherwise in 3.5 process, we run into a recurive assembly resolution // which is trigged by AppContainerUtilities.AttachEventToResolveWinmd method. EqtTrace.SetupRemoteEqtTraceListeners(this.domain); // Add an assembly resolver... Type assemblyResolverType = typeof(AssemblyResolver); if (EqtTrace.IsInfoEnabled) { EqtTrace.Info("TestSourceHost: assemblyenumerator location: {0} , fullname: {1} ", assemblyResolverType.Assembly.Location, assemblyResolverType.FullName); } var resolver = AppDomainUtilities.CreateInstance( this.domain, assemblyResolverType, new object[] { resolutionPaths }); if (EqtTrace.IsInfoEnabled) { EqtTrace.Info( "TestSourceHost: resolver type: {0} , resolve type assembly: {1} ", resolver.GetType().FullName, resolver.GetType().Assembly.Location); } this.assemblyResolver = (AssemblyResolver)resolver; if (adapterSettings != null) { try { var additionalSearchDirectories = adapterSettings.GetDirectoryListWithRecursiveProperty(appDomainSetup.ApplicationBase); if (additionalSearchDirectories?.Count > 0) { this.assemblyResolver.AddSearchDirectoriesFromRunSetting( adapterSettings.GetDirectoryListWithRecursiveProperty(appDomainSetup.ApplicationBase)); } } catch (Exception exception) { if (EqtTrace.IsErrorEnabled) { EqtTrace.Error(exception); } } } }