diff --git a/src/Microsoft.TestPlatform.Client/TestPlatform.cs b/src/Microsoft.TestPlatform.Client/TestPlatform.cs index aac429ba7d..df62dbb1c5 100644 --- a/src/Microsoft.TestPlatform.Client/TestPlatform.cs +++ b/src/Microsoft.TestPlatform.Client/TestPlatform.cs @@ -112,7 +112,6 @@ public ITestRunRequest CreateTestRunRequest(TestRunCriteria testRunCriteria, Pro throw new ArgumentNullException(nameof(testRunCriteria)); } - // Update cache with Extension Folder's files this.AddExtensionAssemblies(testRunCriteria.TestRunSettings); var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(testRunCriteria.TestRunSettings); @@ -201,8 +200,7 @@ private void AddExtensionAssemblies(string runSettings) /// private void AddExtensionAssembliesFromSource(TestRunCriteria testRunCriteria) { - // Find source directories - var sources = testRunCriteria.Sources; + IEnumerable sources = testRunCriteria.Sources; if (testRunCriteria.HasSpecificTests) { // If the test execution is with a test filter, group them by sources @@ -211,6 +209,7 @@ private void AddExtensionAssembliesFromSource(TestRunCriteria testRunCriteria) // Currently we support discovering loggers only from Source directory var loggersToUpdate = new List(); + foreach (var source in sources) { var sourceDirectory = Path.GetDirectoryName(source); diff --git a/src/Microsoft.TestPlatform.Common/Constants.cs b/src/Microsoft.TestPlatform.Common/Constants.cs index e17853afe3..7f813308e7 100644 --- a/src/Microsoft.TestPlatform.Common/Constants.cs +++ b/src/Microsoft.TestPlatform.Common/Constants.cs @@ -68,6 +68,5 @@ public static class TestPlatformConstants /// Regex pattern used to find the settings provider. /// public const string SettingsProviderRegexPattern = @".*SettingsProvider.dll"; - } } diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestDiscoveryExtensionManager.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestDiscoveryExtensionManager.cs index c780a8f2cf..0af7899b12 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestDiscoveryExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestDiscoveryExtensionManager.cs @@ -14,10 +14,10 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework /// /// Responsible for managing the Test Discoverer extensions which are available. /// - internal class TestDiscoveryExtensionManager + internal class TestDiscoveryExtensionManager { #region Fields - + private static TestDiscoveryExtensionManager testDiscoveryExtensionManager; #endregion @@ -79,7 +79,8 @@ public static TestDiscoveryExtensionManager Create() IEnumerable> testExtensions; TestPluginManager.Instance - .GetTestExtensions( + .GetSpecificTestExtensions( + TestPlatformConstants.TestAdapterRegexPattern, out unfilteredTestExtensions, out testExtensions); @@ -106,7 +107,7 @@ public static TestDiscoveryExtensionManager GetDiscoveryExtensionManager(string IEnumerable> testExtensions; TestPluginManager.Instance - .GetTestExtensions( + .GetTestExtensions( extensionAssembly, out unfilteredTestExtensions, out testExtensions); diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExecutorExtensionManager.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExecutorExtensionManager.cs index 63734aca38..37e5ece132 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExecutorExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestExecutorExtensionManager.cs @@ -13,7 +13,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; - + /// /// Manages the the Test Executor extensions. /// @@ -67,12 +67,13 @@ internal static TestExecutorExtensionManager Create() IEnumerable> testExtensions; TestPluginManager.Instance - .GetTestExtensions( + .GetSpecificTestExtensions( + TestPlatformConstants.TestAdapterRegexPattern, out unfilteredTestExtensions, out testExtensions); - + testExecutorExtensionManager = new TestExecutorExtensionManager( - unfilteredTestExtensions, testExtensions, TestSessionMessageLogger.Instance); + unfilteredTestExtensions, testExtensions, TestSessionMessageLogger.Instance); } } } @@ -95,7 +96,7 @@ internal static TestExecutorExtensionManager GetExecutionExtensionManager(string IEnumerable> testExtensions; TestPluginManager.Instance - .GetTestExtensions( + .GetTestExtensions( extensionAssembly, out unfilteredTestExtensions, out testExtensions); diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginCache.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginCache.cs index 8814b163d7..7dc7bfd7e3 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginCache.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginCache.cs @@ -8,6 +8,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework using System.IO; using System.Linq; using System.Reflection; + using System.Text.RegularExpressions; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; using Microsoft.VisualStudio.TestPlatform.Common.Utilities; @@ -32,9 +33,9 @@ public class TestPluginCache private readonly IFileHelper fileHelper; /// - /// Specify the path to additional extensions + /// Specify the path to extensions /// - private IEnumerable pathToAdditionalExtensions; + private List pathToExtensions; /// /// Specifies whether we should load only well known extensions or not. Default is "load all". @@ -47,9 +48,9 @@ public class TestPluginCache private AssemblyResolver assemblyResolver; /// - /// Lock for additional extensions update + /// Lock for extensions update /// - private object lockForAdditionalExtensionsUpdate; + private object lockForExtensionsUpdate; private static TestPluginCache instance; @@ -62,13 +63,17 @@ public class TestPluginCache /// /// Initializes a new instance of the class. /// + /// + /// The file Helper. + /// protected TestPluginCache(IFileHelper fileHelper) { this.resolvedAssemblies = new Dictionary(); - this.pathToAdditionalExtensions = null; + this.pathToExtensions = null; this.loadOnlyWellKnownExtensions = false; - this.lockForAdditionalExtensionsUpdate = new object(); + this.lockForExtensionsUpdate = new object(); this.fileHelper = fileHelper; + this.TestExtensions = null; } #endregion @@ -88,30 +93,20 @@ internal set } } - - /// - /// Gets whether default extensions discovery is done. - /// - public bool AreDefaultExtensionsDiscovered - { - get; - private set; - } - /// - /// The test extensions discovered by the cache until now. + /// Gets the test extensions discovered by the cache until now. /// /// Returns null if discovery of extensions is not done. internal TestExtensions TestExtensions { get; private set; } /// - /// Path to additional extensions + /// Path to extensions /// - public IEnumerable PathToAdditionalExtensions + public IEnumerable PathToExtensions { get { - return this.pathToAdditionalExtensions; + return this.pathToExtensions; } } @@ -131,73 +126,31 @@ public bool LoadOnlyWellKnownExtensions #region Public Methods /// - /// Gets the test extensions defined in the provided extension assembly. + /// Performs discovery of specific type of test extensions. /// - /// The extension assembly. - /// The test extension collection defined in this assembly. - public TestExtensions GetTestExtensions(string extensionAssembly) + /// + /// Type of Plugin info. + /// + /// + /// Type of extension. + /// + /// + /// The regex Pattern. + /// + /// + /// The . of test plugin info. + /// + [System.Security.SecurityCritical] + public Dictionary DiscoverTestExtensions(string regexPattern) + where TPluginInfo : TestPluginInformation { - // Check if extensions from this assembly have already been discovered. - var extensions = this.TestExtensions?.GetExtensionsDiscoveredFromAssembly(extensionAssembly); - - if (extensions != null) + // Return the cached value if cache is valid. + if (this.TestExtensions != null && this.TestExtensions.AreTestExtensionsCached()) { - return extensions; + return this.TestExtensions.GetTestExtensionCache(); } - this.SetupAssemblyResolver(extensionAssembly); - - try - { - EqtTrace.Verbose("TestPluginCache: Discovering the extensions using extension path."); - - extensions = this.GetTestExtensions(new List { extensionAssembly }); - - // Add extensions discovered to the cache. - if (this.TestExtensions == null) - { - this.TestExtensions = extensions; - } - else - { - this.TestExtensions.AddExtensions(extensions); - } - - if (EqtTrace.IsVerboseEnabled) - { - EqtTrace.Verbose( - "TestPluginCache: Discovered extensions from '{0}'.", - extensionAssembly); - } - - this.LogExtensions(); - } -#if NET46 - catch (ThreadAbortException) - { - // Nothing to do here, we just do not want to do an EqtTrace.Fail for this thread - // being aborted as it is a legitimate exception to receive. - if (EqtTrace.IsVerboseEnabled) - { - EqtTrace.Verbose("TestPluginCache.DiscoverTestExtensions: Data extension discovery is being aborted due to a thread abort."); - } - } -#endif - catch (Exception e) - { - EqtTrace.Error("TestPluginCache: Discovery of extension from {0} failed! {1}", extensionAssembly, e); - throw; - } - - return extensions; - } - - /// - /// Performs discovery of data extensions. - /// - [System.Security.SecurityCritical] - public void DiscoverAllTestExtensions() - { + Dictionary pluginInfos = null; this.SetupAssemblyResolver(null); // Some times TestPlatform.core.dll assembly fails to load in the current appdomain (from devenv.exe). @@ -216,29 +169,29 @@ public void DiscoverAllTestExtensions() // Combine all the possible extensions - both default and additional var allExtensionPaths = new List(this.DefaultExtensionPaths); - if (this.pathToAdditionalExtensions != null) + if (this.pathToExtensions != null) { - allExtensionPaths.AddRange(this.pathToAdditionalExtensions); + var filteredExtensions = this.GetFilteredExtensions(this.pathToExtensions, regexPattern); + allExtensionPaths.AddRange(filteredExtensions); } // Discover the test extensions from candidate assemblies. - var extensions = this.GetTestExtensions(allExtensionPaths); + pluginInfos = this.GetTestExtensions(allExtensionPaths); if (this.TestExtensions == null) { - this.TestExtensions = extensions; - } - else - { - this.TestExtensions.AddExtensions(extensions); + this.TestExtensions = new TestExtensions(); } - this.AreDefaultExtensionsDiscovered = true; + this.TestExtensions.AddExtension(pluginInfos); + + // Set the cache bool to true. + this.TestExtensions.SetTestExtensionsCacheStatus(); if (EqtTrace.IsVerboseEnabled) { - var extensionString = this.pathToAdditionalExtensions != null - ? string.Join(",", this.pathToAdditionalExtensions.ToArray()) + var extensionString = this.pathToExtensions != null + ? string.Join(",", this.pathToExtensions.ToArray()) : null; EqtTrace.Verbose( "TestPluginCache: Discovered the extensions using extension path '{0}'.", @@ -277,14 +230,16 @@ public void DiscoverAllTestExtensions() this.resolvedAssemblies?.Clear(); } } + + return pluginInfos; } /// /// Use the parameter path to extensions /// - public void UpdateAdditionalExtensions(IEnumerable additionalExtensionsPath, bool shouldLoadOnlyWellKnownExtensions) + public void UpdateExtensions(IEnumerable additionalExtensionsPath, bool shouldLoadOnlyWellKnownExtensions) { - lock (this.lockForAdditionalExtensionsUpdate) + lock (this.lockForExtensionsUpdate) { EqtTrace.Verbose( "TestPluginCache: Updating loadOnlyWellKnownExtensions from {0} to {1}.", @@ -300,12 +255,12 @@ public void UpdateAdditionalExtensions(IEnumerable additionalExtensionsP } string extensionString; - if (this.pathToAdditionalExtensions != null - && extensions.Count == this.pathToAdditionalExtensions.Count() - && extensions.All(e => this.pathToAdditionalExtensions.Contains(e))) + if (this.pathToExtensions != null + && extensions.Count == this.pathToExtensions.Count() + && extensions.All(e => this.pathToExtensions.Contains(e))) { - extensionString = this.pathToAdditionalExtensions != null - ? string.Join(",", this.pathToAdditionalExtensions.ToArray()) + extensionString = this.pathToExtensions != null + ? string.Join(",", this.pathToExtensions.ToArray()) : null; EqtTrace.Verbose( "TestPluginCache: Ignoring the new extensions update as there is no change. Current extensions are '{0}'.", @@ -321,29 +276,29 @@ public void UpdateAdditionalExtensions(IEnumerable additionalExtensionsP // an error. var newExtensionPaths = extensions.Select(Path.GetFullPath).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); - if (this.pathToAdditionalExtensions != null) + if (this.pathToExtensions != null) { - newExtensionPaths.AddRange(this.pathToAdditionalExtensions); + newExtensionPaths.AddRange(this.pathToExtensions); } // Use the new paths and set the extensions discovered to false so that the next time // any one tries to get the additional extensions, we rediscover. - this.pathToAdditionalExtensions = newExtensionPaths; + this.pathToExtensions = newExtensionPaths; - this.AreDefaultExtensionsDiscovered = false; + this.TestExtensions?.InvalidateCache(); if (EqtTrace.IsVerboseEnabled) { var directories = - this.pathToAdditionalExtensions.Select(e => Path.GetDirectoryName(Path.GetFullPath(e))).Distinct(); + this.pathToExtensions.Select(e => Path.GetDirectoryName(Path.GetFullPath(e))).Distinct(); var directoryString = directories != null ? string.Join(",", directories.ToArray()) : null; EqtTrace.Verbose( "TestPluginCache: Using directories for assembly resolution '{0}'.", directoryString); - extensionString = this.pathToAdditionalExtensions != null - ? string.Join(",", this.pathToAdditionalExtensions.ToArray()) + extensionString = this.pathToExtensions != null + ? string.Join(",", this.pathToExtensions.ToArray()) : null; EqtTrace.Verbose("TestPluginCache: Updated the available extensions to '{0}'.", extensionString); } @@ -393,16 +348,58 @@ internal virtual string[] GetFilesInDirectory(string path, string searchPattern) } /// - /// Gets the test extensions defined in the extension assembly list. + /// Get the files which match the regex pattern /// - /// Extension assembly paths. - /// List of extensions. - /// Added to mock out dependency from the actual test plugin discovery as such. - internal virtual TestExtensions GetTestExtensions(IEnumerable extensionPaths) + /// + /// The extensions. + /// + /// + /// Regex search pattern of extension. + /// + /// + /// The list of files which match the regex pattern + /// + internal virtual List GetFilteredExtensions(List extensions, string searchPattern) { - var discoverer = new TestPluginDiscoverer(); + var regex = new Regex(searchPattern, RegexOptions.IgnoreCase); + return extensions.Where(ext => regex.IsMatch(ext)).ToList(); + } + + /// + /// The get test extensions. + /// + /// + /// The extension assembly. + /// + /// + /// Type of Test plugin info. + /// + /// + /// Type of extension. + /// + /// + /// The . + /// + internal virtual Dictionary GetTestExtensions(string extensionAssembly) where TPluginInfo : TestPluginInformation + { + // Check if extensions from this assembly have already been discovered. + var extensions = this.TestExtensions?.GetExtensionsDiscoveredFromAssembly(this.TestExtensions.GetTestExtensionCache(), extensionAssembly); - return discoverer.GetTestExtensionsInformation(extensionPaths, this.loadOnlyWellKnownExtensions); + if (extensions != null) + { + return extensions; + } + + var pluginInfos = this.GetTestExtensions(new List() { extensionAssembly }); + + // Add extensions discovered to the cache. + if (this.TestExtensions == null) + { + this.TestExtensions = new TestExtensions(); + } + + this.TestExtensions.AddExtension(pluginInfos); + return pluginInfos; } /// @@ -435,7 +432,7 @@ internal IList GetDefaultResolutionPaths() { var resolutionPaths = new List(); - var extensionDirectories = this.pathToAdditionalExtensions?.Select(e => Path.GetDirectoryName(Path.GetFullPath(e))).Distinct(); + var extensionDirectories = this.pathToExtensions?.Select(e => Path.GetDirectoryName(Path.GetFullPath(e))).Distinct(); if (extensionDirectories != null && extensionDirectories.Any()) { resolutionPaths.AddRange(extensionDirectories); @@ -457,6 +454,36 @@ internal IList GetDefaultResolutionPaths() return resolutionPaths; } + /// + /// Gets the test extensions defined in the extension assembly list. + /// + /// + /// Type of PluginInfo. + /// + /// + /// Type of Extension. + /// + /// + /// Extension assembly paths. + /// + /// + /// List of extensions. + /// + /// + /// Added to mock out dependency from the actual test plugin discovery as such. + /// + private Dictionary GetTestExtensions(IEnumerable extensionPaths) where TPluginInfo : TestPluginInformation + { + foreach (var extensionPath in extensionPaths) + { + this.SetupAssemblyResolver(extensionPath); + } + + var discoverer = new TestPluginDiscoverer(); + + return discoverer.GetTestExtensionsInformation(extensionPaths, this.loadOnlyWellKnownExtensions); + } + private void SetupAssemblyResolver(string extensionAssembly) { IList resolutionPaths; diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs index 997d539004..3f73f767aa 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs @@ -13,9 +13,6 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; using Microsoft.VisualStudio.TestPlatform.ObjectModel; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; #if !NET46 using System.Runtime.Loader; #endif @@ -50,35 +47,26 @@ internal class TestPluginDiscoverer /// /// Gets information about each of the test extensions available. /// - /// The path to the extensions. - /// Should load only well known extensions or all. - /// The . - public TestExtensions GetTestExtensionsInformation( - IEnumerable pathToExtensions, - bool loadOnlyWellKnownExtensions) + /// + /// The path to the extensions. + /// + /// + /// Should load only well known extensions or all. + /// + /// + /// The ` of assembly qualified name and testplugin information. + /// + public Dictionary GetTestExtensionsInformation( + IEnumerable extensionPaths, + bool loadOnlyWellKnownExtensions) where TPluginInfo : TestPluginInformation { - Debug.Assert(pathToExtensions != null); - - var testExtensions = new TestExtensions - { - TestDiscoverers = new Dictionary(StringComparer.OrdinalIgnoreCase), - TestExecutors = new Dictionary(StringComparer.OrdinalIgnoreCase), - TestSettingsProviders = new Dictionary(StringComparer.OrdinalIgnoreCase), - TestLoggers = new Dictionary(StringComparer.OrdinalIgnoreCase), - TestHosts = new Dictionary(StringComparer.OrdinalIgnoreCase) - }; + Debug.Assert(extensionPaths != null); + var pluginInfos = new Dictionary(); #if !WINDOWS_UAP - this.GetTestExtensionsFromFiles( - pathToExtensions.ToArray(), - loadOnlyWellKnownExtensions, - testExtensions.TestDiscoverers, - testExtensions.TestExecutors, - testExtensions.TestSettingsProviders, - testExtensions.TestLoggers, - testExtensions.TestHosts); + this.GetTestExtensionsFromFiles(extensionPaths.ToArray(), loadOnlyWellKnownExtensions, pluginInfos); #else var fileSearchTask = Windows.ApplicationModel.Package.Current.InstalledLocation.GetFilesAsync().AsTask(); @@ -94,31 +82,22 @@ public TestExtensions GetTestExtensionsInformation( ). Select(file => file.Name); - GetTestExtensionsFromFiles( - binaries.ToArray(), - loadOnlyWellKnownExtensions, - testDiscoverers, - testExecutors, - testSettingsProviders, - testLoggers); + GetTestExtensionsFromFiles(binaries.ToArray(), loadOnlyWellKnownExtensions, pluginInfos); // In Release mode - managed dlls are packaged differently // So, file search will not find them - do it manually if (testDiscoverers.Count < 1) { - GetTestExtensionsFromFiles( + GetTestExtensionsFromFiles( new string[3] { "Microsoft.VisualStudio.TestPlatform.Extensions.MSAppContainerAdapter.dll", "Microsoft.VisualStudio.TestTools.CppUnitTestFramework.CppUnitTestExtension.dll", "Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dll",}, loadOnlyWellKnownExtensions, - testDiscoverers, - testExecutors, - testSettingsProviders, - testLoggers); + pluginInfos); } #endif - return testExtensions; + return pluginInfos; } #endregion @@ -128,28 +107,30 @@ public TestExtensions GetTestExtensionsInformation( /// /// Gets test extension information from the given colletion of files. /// - /// List of dll's to check for test extension availability - /// Should load only well known extensions or all. - /// Test discoverers collection to add to. - /// Test executors collection to add to. - /// Test settings providers collection to add to. - /// Test loggers collection to add to. + /// + /// Type of Test Plugin Information. + /// + /// + /// Type of extension. + /// + /// + /// List of dll's to check for test extension availability + /// + /// + /// Should load only well known extensions or all. + /// + /// + /// Test plugins collection to add to. + /// [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We would like to continue discovering all plugins even if some dll in Extensions folder is not able to be load properly")] - private void GetTestExtensionsFromFiles( - string[] files, - bool loadOnlyWellKnownExtensions, - Dictionary testDiscoverers, - Dictionary testExecutors, - Dictionary testSettingsProviders, - Dictionary testLoggers, - Dictionary testHosts) + private void GetTestExtensionsFromFiles( + string[] files, + bool loadOnlyWellKnownExtensions, + Dictionary pluginInfos) where TPluginInfo : TestPluginInformation { Debug.Assert(files != null, "null files"); - Debug.Assert(testDiscoverers != null, "null testDiscoverers"); - Debug.Assert(testExecutors != null, "null testExecutors"); - Debug.Assert(testSettingsProviders != null, "null testSettingsProviders"); - Debug.Assert(testLoggers != null, "null testLoggers"); + Debug.Assert(pluginInfos != null, "null pluginInfos"); // TODO: Do not see why loadOnlyWellKnowExtensions is still needed. //AssemblyName executingAssemblyName = null; @@ -186,7 +167,7 @@ private void GetTestExtensionsFromFiles( if (assembly != null) { - this.GetTestExtensionsFromAssembly(assembly, testDiscoverers, testExecutors, testSettingsProviders, testLoggers, testHosts); + this.GetTestExtensionsFromAssembly(assembly, pluginInfos); } } } @@ -195,25 +176,19 @@ private void GetTestExtensionsFromFiles( /// Gets test extensions from a given assembly. /// /// Assembly to check for test extension availability - /// Test discoverers collection to add to. - /// Test executors collection to add to. - /// Test settings providers collection to add to. - /// Test loggers collection to add to. - private void GetTestExtensionsFromAssembly( - Assembly assembly, - Dictionary testDiscoverers, - Dictionary testExecutors, - Dictionary testSettingsProviders, - Dictionary testLoggers, - Dictionary testHosts) + /// Test extensions collection to add to. + /// + /// Type of Test Plugin Information. + /// + /// + /// Type of Extensions. + /// + private void GetTestExtensionsFromAssembly(Assembly assembly, Dictionary pluginInfos) where TPluginInfo : TestPluginInformation { Debug.Assert(assembly != null, "null assembly"); - Debug.Assert(testDiscoverers != null, "null testDiscoverers"); - Debug.Assert(testExecutors != null, "null testExecutors"); - Debug.Assert(testSettingsProviders != null, "null testSettingsProviders"); - Debug.Assert(testLoggers != null, "null testLoggers"); + Debug.Assert(pluginInfos != null, "null pluginInfos"); - Type[] types = null; + Type[] types; try { types = assembly.GetTypes(); @@ -239,11 +214,7 @@ private void GetTestExtensionsFromAssembly( { if (type.GetTypeInfo().IsClass && !type.GetTypeInfo().IsAbstract) { - this.GetTestExtensionFromType(type, typeof(ITestDiscoverer), testDiscoverers); - this.GetTestExtensionFromType(type, typeof(ITestExecutor), testExecutors); - this.GetTestExtensionFromType(type, typeof(ITestLogger), testLoggers); - this.GetTestExtensionFromType(type, typeof(ISettingsProvider), testSettingsProviders); - this.GetTestExtensionFromType(type, typeof(ITestRuntimeProvider), testHosts); + this.GetTestExtensionFromType(type, typeof(TExtension), pluginInfos); } } } @@ -252,21 +223,28 @@ private void GetTestExtensionsFromAssembly( /// /// Attempts to find a test extension from given type. /// - /// Data type of the test plugin information - /// Type to inspect for being test extension - /// Test extension type to look for. - /// Test extensions collection to add to. - /// True if test extension is found, false otherwise. + /// + /// Type of the test plugin information + /// + /// + /// Type to inspect for being test extension + /// + /// + /// Test extension type to look for. + /// + /// + /// Test extensions collection to add to. + /// private void GetTestExtensionFromType( - Type type, - Type extensionType, - Dictionary extensionCollection) - where TPluginInfo : TestPluginInformation + Type type, + Type extensionType, + Dictionary extensionCollection) + where TPluginInfo : TestPluginInformation { if (extensionType.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())) { - var dataObject = Activator.CreateInstance(typeof(TPluginInfo), type); - var pluginInfo = (TPluginInfo)dataObject; + var rawPluginInfo = Activator.CreateInstance(typeof(TPluginInfo), type); + var pluginInfo = (TPluginInfo)rawPluginInfo; if (extensionCollection.ContainsKey(pluginInfo.IdentifierData)) { diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginManager.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginManager.cs index 729d935fcf..31668d5274 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginManager.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginManager.cs @@ -5,11 +5,8 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework { using System; using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; using System.Reflection; - using Interfaces; - using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; @@ -111,6 +108,7 @@ public static T CreateTestExtension(Type extensionType) { EqtTrace.Error("TestPluginManager.CreateTestExtension: Could not create instance of type: " + extensionType.ToString() + " Exception: " + ex); } + throw; } } @@ -122,39 +120,63 @@ public static T CreateTestExtension(Type extensionType) /// /// Retrieves the test extension collections of given extension type. /// - /// Type of the required extensions - /// Type of metadata of required extensions - /// Concrete type of metadata - /// Receives unfiltered list of test extensions - /// Receives test extensions filtered by Identifier data - public void GetTestExtensions( + /// + /// Type of the required extensions + /// + /// + /// Type of metadata of required extensions + /// + /// + /// Concrete type of metadata + /// + /// + /// The regex Pattern. + /// + /// + /// Receives unfiltered list of test extensions + /// + /// + /// Receives test extensions filtered by Identifier data + /// + public void GetSpecificTestExtensions( + string regexPattern, out IEnumerable>> unfiltered, - out IEnumerable> filtered) where TMetadata : IMetadata + out IEnumerable> filtered) where TMetadata : IMetadata where TPluginInfo : TestPluginInformation { - if (!TestPluginCache.Instance.AreDefaultExtensionsDiscovered) - { - TestPluginCache.Instance.DiscoverAllTestExtensions(); - } - - this.GetExtensions(TestPluginCache.Instance.TestExtensions, out unfiltered, out filtered); + var extensions = TestPluginCache.Instance.DiscoverTestExtensions(regexPattern); + this.GetExtensions(extensions, out unfiltered, out filtered); } /// /// Retrieves the test extension collections of given extension type for the provided extension assembly. /// - /// The extension assembly. - /// Type of the required extensions - /// Type of metadata of required extensions - /// Concrete type of metadata - /// Receives unfiltered list of test extensions - /// Receives test extensions filtered by Identifier data - public void GetTestExtensions( + /// + /// The extension assembly. + /// + /// + /// + /// + /// Type of the required extensions + /// + /// + /// Type of metadata of required extensions + /// + /// + /// Concrete type of metadata + /// + /// + /// Receives unfiltered list of test extensions + /// + /// + /// Receives test extensions filtered by Identifier data + /// + public void GetTestExtensions( string extensionAssembly, out IEnumerable>> unfiltered, - out IEnumerable> filtered) where TMetadata : IMetadata + out IEnumerable> filtered) where TMetadata : IMetadata where TPluginInfo : TestPluginInformation { - var extensions = TestPluginCache.Instance.GetTestExtensions(extensionAssembly); - this.GetExtensions(extensions, out unfiltered, out filtered); + var extensions = TestPluginCache.Instance.GetTestExtensions(extensionAssembly); + this.GetExtensions(extensions, out unfiltered, out filtered); } #endregion @@ -182,21 +204,35 @@ private IEnumerable GetValuesFromDictionary(Dictionary /// /// Gets unfiltered and filtered extensions from the provided test extension collection. /// - /// Type of the required extensions - /// Type of metadata of required extensions - /// Concrete type of metadata - /// The test extension collection list. - /// Receives unfiltered list of test extensions - /// Receives test extensions filtered by Identifier data - private void GetExtensions( - TestExtensions testExtensions, + /// + /// + /// + /// Type of the required extensions + /// + /// + /// Type of metadata of required extensions + /// + /// + /// Concrete type of metadata + /// + /// + /// The test extension dictionary. + /// + /// + /// Receives unfiltered list of test extensions + /// + /// + /// Receives test extensions filtered by Identifier data + /// + private void GetExtensions( + Dictionary testPluginInfo, out IEnumerable>> unfiltered, - out IEnumerable> filtered) where TMetadata : IMetadata + out IEnumerable> filtered) where TMetadata : IMetadata where TPluginInfo : TestPluginInformation { var unfilteredExtensions = new List>>(); var filteredExtensions = new List>(); - var testPlugins = this.GetExtensionsCollection(testExtensions, typeof(IExtension)); + var testPlugins = this.GetValuesFromDictionary(testPluginInfo); foreach (var plugin in testPlugins) { var testExtension = new LazyExtension(plugin, typeof(TMetadata)); @@ -213,41 +249,6 @@ private void GetExtensions( filtered = filteredExtensions; } - /// - /// Helper to fetch appropriate test plugin information collection depending upon the extension data type. - /// - /// The extensions. - /// Data type of the test extension - /// Collection of test extensions of the given type - private IEnumerable GetExtensionsCollection(TestExtensions extensions, Type extensionType) - { - if (typeof(ITestDiscoverer).GetTypeInfo().IsAssignableFrom(extensionType)) - { - return this.GetValuesFromDictionary(extensions.TestDiscoverers); - } - else if (typeof(ITestExecutor).GetTypeInfo().IsAssignableFrom(extensionType)) - { - return this.GetValuesFromDictionary(extensions.TestExecutors); - } - else if (typeof(ISettingsProvider).GetTypeInfo().IsAssignableFrom(extensionType)) - { - return this.GetValuesFromDictionary(extensions.TestSettingsProviders); - } - else if (typeof(ITestLogger).GetTypeInfo().IsAssignableFrom(extensionType)) - { - return this.GetValuesFromDictionary(extensions.TestLoggers); - } - else if (typeof(ITestRuntimeProvider).GetTypeInfo().IsAssignableFrom(extensionType)) - { - return this.GetValuesFromDictionary(extensions.TestHosts); - } - else - { - EqtTrace.Info("TestExtensionsManager.GetExtesnionsCollection: Failed to get test extensions colleciton for type {0}", extensionType); - return null; - } - } - #endregion } } diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/Utilities/TestExtensions.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/Utilities/TestExtensions.cs index b55eae11bb..2153a6bc8a 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/Utilities/TestExtensions.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/Utilities/TestExtensions.cs @@ -22,26 +22,51 @@ public class TestExtensions /// internal Dictionary TestDiscoverers { get; set; } + /// + /// Gets or sets a value indicating whether are test discoverers cached. + /// + internal bool AreTestDiscoverersCached { get; set; } + /// /// Gets or sets test executor extensions. /// internal Dictionary TestExecutors { get; set; } + /// + /// Gets or sets a value indicating whether are test executors cached. + /// + internal bool AreTestExecutorsCached { get; set; } + /// /// Gets or sets test setting provider extensions. /// internal Dictionary TestSettingsProviders { get; set; } + /// + /// Gets or sets a value indicating whether are test settings providers cached. + /// + internal bool AreTestSettingsProvidersCached { get; set; } + /// /// Gets or sets test logger extensions. /// internal Dictionary TestLoggers { get; set; } + /// + /// Gets or sets a value indicating whether are test loggers cached. + /// + internal bool AreTestLoggersCached { get; set; } + /// /// Gets or sets test logger extensions. /// internal Dictionary TestHosts { get; set; } + /// + /// Gets or sets a value indicating whether are test hosts cached. + /// + internal bool AreTestHostsCached { get; set; } + #endregion #region Internal methods @@ -49,19 +74,45 @@ public class TestExtensions /// /// Adds the extensions specified to the current set of extensions. /// - /// The test extensions to add. - internal void AddExtensions(TestExtensions extensions) + /// + /// Type of plugin info. + /// + /// + /// The info about new extensions discovered + /// + /// + /// The of extensions discovered + /// + internal Dictionary AddExtension( + Dictionary newExtensions) where TPluginInfo : TestPluginInformation { - if (extensions == null) + var existingExtensions = this.GetTestExtensionCache(); + if (newExtensions == null) + { + return existingExtensions; + } + + if (existingExtensions == null) + { + this.SetTestExtensionCache(newExtensions); + return newExtensions; + } + + foreach (var extension in newExtensions) { - return; + if (existingExtensions.ContainsKey(extension.Key)) + { + EqtTrace.Warning( + "TestExtensions.AddExtensions: Attempt to add multiple test extensions with identifier data '{0}'", + extension.Key); + } + else + { + existingExtensions.Add(extension.Key, extension.Value); + } } - this.TestDiscoverers = this.AddExtension(this.TestDiscoverers, extensions.TestDiscoverers); - this.TestExecutors = this.AddExtension(this.TestExecutors, extensions.TestExecutors); - this.TestSettingsProviders = this.AddExtension(this.TestSettingsProviders, extensions.TestSettingsProviders); - this.TestLoggers = this.AddExtension(this.TestLoggers, extensions.TestLoggers); - this.TestHosts = this.AddExtension(this.TestHosts, extensions.TestHosts); + return existingExtensions; } /// @@ -94,7 +145,7 @@ internal TestExtensions GetExtensionsDiscoveredFromAssembly(string extensionAsse this.TestHosts, extensionAssembly); - if (testExtensions.TestDiscoverers.Any() || testExtensions.TestExecutors.Any() || testExtensions.TestSettingsProviders.Any() || + if (testExtensions.TestDiscoverers.Any() || testExtensions.TestExecutors.Any() || testExtensions.TestSettingsProviders.Any() || testExtensions.TestLoggers.Any() || testExtensions.TestHosts.Any()) { // This extension has already been discovered. @@ -104,43 +155,122 @@ internal TestExtensions GetExtensionsDiscoveredFromAssembly(string extensionAsse return null; } - #endregion + internal Dictionary GetTestExtensionCache() where TPluginInfo : TestPluginInformation + { + if (typeof(TPluginInfo) == typeof(TestDiscovererPluginInformation)) + { + return (Dictionary)(object)this.TestDiscoverers; + } + else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation)) + { + return (Dictionary)(object)this.TestExecutors; + } + else if (typeof(TPluginInfo) == typeof(TestLoggerPluginInformation)) + { + return (Dictionary)(object)this.TestLoggers; + } + else if (typeof(TPluginInfo) == typeof(TestSettingsProviderPluginInformation)) + { + return (Dictionary)(object)this.TestSettingsProviders; + } + else if (typeof(TPluginInfo) == typeof(TestRuntimePluginInformation)) + { + return (Dictionary)(object)this.TestHosts; + } - #region Private methods + return null; + } - private Dictionary AddExtension( - Dictionary existingExtensions, - Dictionary newExtensions) + /// + /// The are test extensions cached. + /// + /// + /// + /// + /// The . + /// + internal bool AreTestExtensionsCached() where TPluginInfo : TestPluginInformation { - if (newExtensions == null) + if (typeof(TPluginInfo) == typeof(TestDiscovererPluginInformation)) { - return null; + return this.AreTestDiscoverersCached; + } + else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation)) + { + return this.AreTestExecutorsCached; + } + else if (typeof(TPluginInfo) == typeof(TestLoggerPluginInformation)) + { + return this.AreTestLoggersCached; + } + else if (typeof(TPluginInfo) == typeof(TestSettingsProviderPluginInformation)) + { + return this.AreTestSettingsProvidersCached; + } + else if (typeof(TPluginInfo) == typeof(TestRuntimePluginInformation)) + { + return this.AreTestHostsCached; } - if (existingExtensions == null) + return false; + } + + /// + /// The set test extensions cache status. + /// + /// + /// + internal void SetTestExtensionsCacheStatus() where TPluginInfo : TestPluginInformation + { + if (typeof(TPluginInfo) == typeof(TestDiscovererPluginInformation)) { - return newExtensions; + this.AreTestDiscoverersCached = true; } - else + else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation)) { - foreach (var extension in newExtensions) - { - if (existingExtensions.ContainsKey(extension.Key)) - { - EqtTrace.Warning( - "TestExtensions.AddExtensions: Attempt to add multiple test extensions with identifier data '{0}'", - extension.Key); - } - else - { - existingExtensions.Add(extension.Key, extension.Value); - } - } - return existingExtensions; + this.AreTestExecutorsCached = true; + } + else if (typeof(TPluginInfo) == typeof(TestLoggerPluginInformation)) + { + this.AreTestLoggersCached = true; + } + else if (typeof(TPluginInfo) == typeof(TestSettingsProviderPluginInformation)) + { + this.AreTestSettingsProvidersCached = true; + } + else if (typeof(TPluginInfo) == typeof(TestRuntimePluginInformation)) + { + this.AreTestHostsCached = true; } } - private Dictionary GetExtensionsDiscoveredFromAssembly(Dictionary extensionCollection, string extensionAssembly) + /// + /// The invalidate cache of plugin infos. + /// + internal void InvalidateCache() + { + this.AreTestDiscoverersCached = false; + this.AreTestExecutorsCached = false; + this.AreTestLoggersCached = false; + this.AreTestSettingsProvidersCached = false; + this.AreTestHostsCached = false; + } + + /// + /// Gets extensions discovered from assembly. + /// + /// + /// The extension collection. + /// + /// + /// The extension assembly. + /// + /// + /// + /// + /// The . of extensions discovered in assembly + /// + internal Dictionary GetExtensionsDiscoveredFromAssembly(Dictionary extensionCollection, string extensionAssembly) { var extensions = new Dictionary(); if (extensionCollection != null) @@ -160,5 +290,33 @@ private Dictionary GetExtensionsDiscoveredFromAssembly(Dictionary testPluginInfos) where TPluginInfo : TestPluginInformation + { + if (typeof(TPluginInfo) == typeof(TestDiscovererPluginInformation)) + { + this.TestDiscoverers = (Dictionary)(object)testPluginInfos; + } + else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation)) + { + this.TestExecutors = (Dictionary)(object)testPluginInfos; + } + else if (typeof(TPluginInfo) == typeof(TestLoggerPluginInformation)) + { + this.TestLoggers = (Dictionary)(object)testPluginInfos; + } + else if (typeof(TPluginInfo) == typeof(TestSettingsProviderPluginInformation)) + { + this.TestSettingsProviders = (Dictionary)(object)testPluginInfos; + } + else if (typeof(TPluginInfo) == typeof(TestRuntimePluginInformation)) + { + this.TestHosts = (Dictionary)(object)testPluginInfos; + } + } + + #endregion } } diff --git a/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeExtensionManager.cs b/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeExtensionManager.cs index f2089686a8..55df40b222 100644 --- a/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeExtensionManager.cs @@ -55,7 +55,8 @@ public static TestRuntimeExtensionManager Create(IMessageLogger messageLogger) IEnumerable> filteredTestExtensions; IEnumerable>> unfilteredTestExtensions; - TestPluginManager.Instance.GetTestExtensions( + TestPluginManager.Instance.GetSpecificTestExtensions( + TestPlatformConstants.RunTimeRegexPattern, out unfilteredTestExtensions, out filteredTestExtensions); diff --git a/src/Microsoft.TestPlatform.Common/Logging/TestLoggerExtensionManager.cs b/src/Microsoft.TestPlatform.Common/Logging/TestLoggerExtensionManager.cs index 388c8cea00..aabfe8129f 100644 --- a/src/Microsoft.TestPlatform.Common/Logging/TestLoggerExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/Logging/TestLoggerExtensionManager.cs @@ -3,12 +3,13 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.Logging { + using System.Collections.Generic; + using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; - using System.Collections.Generic; /// /// Manages loading and provides access to logging extensions implementing the @@ -17,7 +18,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.Logging internal class TestLoggerExtensionManager : TestExtensionManager { /// - /// Default constructor. + /// Initializes a new instance of the class. /// /// /// The unfiltered Test Extensions. @@ -53,12 +54,12 @@ public static TestLoggerExtensionManager Create(IMessageLogger messageLogger) IEnumerable> filteredTestExtensions; IEnumerable>> unfilteredTestExtensions; - TestPluginManager.Instance.GetTestExtensions( + TestPluginManager.Instance.GetSpecificTestExtensions( + TestPlatformConstants.TestLoggerRegexPattern, out unfilteredTestExtensions, out filteredTestExtensions); return new TestLoggerExtensionManager(unfilteredTestExtensions, filteredTestExtensions, messageLogger); } } - } diff --git a/src/Microsoft.TestPlatform.Common/SettingsProvider/SettingsProviderExtensionManager.cs b/src/Microsoft.TestPlatform.Common/SettingsProvider/SettingsProviderExtensionManager.cs index 47cfac048c..6f72eae7a6 100644 --- a/src/Microsoft.TestPlatform.Common/SettingsProvider/SettingsProviderExtensionManager.cs +++ b/src/Microsoft.TestPlatform.Common/SettingsProvider/SettingsProviderExtensionManager.cs @@ -15,7 +15,6 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.SettingsProvider using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; - using Microsoft.VisualStudio.TestPlatform.Utilities; using CommonResources = Microsoft.VisualStudio.TestPlatform.Common.Resources.Resources; using ObjectModelCommonResources = Microsoft.VisualStudio.TestPlatform.ObjectModel.Resources.CommonResources; @@ -30,7 +29,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.SettingsProvider public class SettingsProviderExtensionManager { #region Fields - + private static SettingsProviderExtensionManager settingsProviderExtensionManager; private static object synclock = new object(); @@ -116,17 +115,17 @@ public static SettingsProviderExtensionManager Create() IEnumerable> testExtensions; TestPluginManager.Instance - .GetTestExtensions - ( + .GetSpecificTestExtensions( + TestPlatformConstants.SettingsProviderRegexPattern, out unfilteredTestExtensions, out testExtensions); - + settingsProviderExtensionManager = new SettingsProviderExtensionManager( - testExtensions, unfilteredTestExtensions, TestSessionMessageLogger.Instance); + testExtensions, unfilteredTestExtensions, TestSessionMessageLogger.Instance); } } } - + return settingsProviderExtensionManager; } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs index 93d211c910..a47dc21ff7 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs @@ -6,17 +6,17 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client using System; using System.Collections.Generic; using System.Linq; + using System.Text.RegularExpressions; + using Microsoft.VisualStudio.TestPlatform.Common; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; - using System.Text.RegularExpressions; - using Microsoft.VisualStudio.TestPlatform.Common; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; /// /// Orchestrates discovery operations for the engine communicating with the client. @@ -122,14 +122,14 @@ private void InitializeExtensions(IEnumerable sources) { var sourceList = sources.ToList(); var extensions = this.testHostManager.GetTestPlatformExtensions(sourceList, TestPluginCache.Instance.DefaultExtensionPaths).ToList(); - if (TestPluginCache.Instance.PathToAdditionalExtensions != null) + if (TestPluginCache.Instance.PathToExtensions != null) { var regex = new Regex(TestPlatformConstants.TestAdapterRegexPattern, RegexOptions.IgnoreCase); - extensions.AddRange(TestPluginCache.Instance.PathToAdditionalExtensions.Where(ext => regex.IsMatch(ext))); + extensions.AddRange(TestPluginCache.Instance.PathToExtensions.Where(ext => regex.IsMatch(ext))); } // Only send this if needed. - if (extensions.Count > 0) + if (extensions.Count() > 0) { this.SetupChannel(sourceList); diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs index fd97b3761d..4f80d9774d 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs @@ -9,15 +9,14 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client using System.Linq; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; - using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Constants = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Constants; using System.Text.RegularExpressions; @@ -163,14 +162,14 @@ private void InitializeExtensions(IEnumerable sources) { var sourceList = sources.ToList(); var extensions = this.testHostManager.GetTestPlatformExtensions(sourceList, TestPluginCache.Instance.DefaultExtensionPaths).ToList(); - if (TestPluginCache.Instance.PathToAdditionalExtensions != null) + if (TestPluginCache.Instance.PathToExtensions != null) { var regex = new Regex(TestPlatformConstants.TestAdapterRegexPattern, RegexOptions.IgnoreCase); - extensions.AddRange(TestPluginCache.Instance.PathToAdditionalExtensions.Where(ext => (regex.IsMatch(ext)))); + extensions.AddRange(TestPluginCache.Instance.PathToExtensions.Where(ext => (regex.IsMatch(ext)))); } // Only send this if needed. - if (extensions.Count > 0) + if (extensions.Count() > 0) { this.SetupChannel(sourceList); diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs index 2897899529..f569071934 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs @@ -62,7 +62,7 @@ public void Initialize(IEnumerable pathToAdditionalExtensions) this.testPlatformEventSource.AdapterSearchStart(); // Start using these additional extensions - TestPluginCache.Instance.UpdateAdditionalExtensions(pathToAdditionalExtensions, shouldLoadOnlyWellKnownExtensions: false); + TestPluginCache.Instance.DefaultExtensionPaths = pathToAdditionalExtensions; // Load and Initialize extensions. TestDiscoveryExtensionManager.LoadAndInitializeAllExtensions(false); @@ -84,10 +84,10 @@ public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEve try { EqtTrace.Info("TestDiscoveryManager.DoDiscovery: Background test discovery started."); - + this.testDiscoveryEventsHandler = eventHandler; - + var verifiedExtensionSourceMap = new Dictionary>(); // Validate the sources @@ -113,12 +113,12 @@ public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEve { // Discovery complete. Raise the DiscoveryCompleteEvent. EqtTrace.Verbose("TestDiscoveryManager.DoDiscovery: Background Test Discovery complete."); - + var totalDiscoveredTestCount = discoveryResultCache.TotalDiscoveredTests; var lastChunk = discoveryResultCache.Tests; EqtTrace.Verbose("TestDiscoveryManager.DiscoveryComplete: Calling DiscoveryComplete callback."); - + if (eventHandler != null) { eventHandler.HandleDiscoveryComplete(totalDiscoveredTestCount, lastChunk, false); @@ -128,7 +128,7 @@ public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEve EqtTrace.Warning( "DiscoveryManager: Could not pass the discovery complete message as the callback is null."); } - + EqtTrace.Verbose("TestDiscoveryManager.DiscoveryComplete: Called DiscoveryComplete callback."); this.testDiscoveryEventsHandler = null; @@ -167,7 +167,7 @@ internal static IEnumerable GetValidSources(IEnumerable sources, { Debug.Assert(sources != null, "sources"); var verifiedSources = new HashSet(StringComparer.OrdinalIgnoreCase); - + foreach (string source in sources) { if (!File.Exists(source)) @@ -198,7 +198,7 @@ internal static IEnumerable GetValidSources(IEnumerable sources, return verifiedSources; } - + // Log the sources from where tests are being discovered if (EqtTrace.IsInfoEnabled) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs index 6731c4e7a6..545eb0e1b0 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs @@ -54,7 +54,7 @@ public void Initialize(IEnumerable pathToAdditionalExtensions) this.testPlatformEventSource.AdapterSearchStart(); // Start using these additional extensions - TestPluginCache.Instance.UpdateAdditionalExtensions(pathToAdditionalExtensions, shouldLoadOnlyWellKnownExtensions: false); + TestPluginCache.Instance.DefaultExtensionPaths = pathToAdditionalExtensions; this.LoadExtensions(); this.testPlatformEventSource.AdapterSearchStop(); diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/TestExtensionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/TestExtensionManager.cs index 9b0022cb27..29569ab7c5 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/TestExtensionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/TestExtensionManager.cs @@ -15,7 +15,7 @@ public class TestExtensionManager : ITestExtensionManager { public void UseAdditionalExtensions(IEnumerable pathToAdditionalExtensions, bool loadOnlyWellKnownExtensions) { - TestPluginCache.Instance.UpdateAdditionalExtensions(pathToAdditionalExtensions, loadOnlyWellKnownExtensions); + TestPluginCache.Instance.UpdateExtensions(pathToAdditionalExtensions, loadOnlyWellKnownExtensions); } } } diff --git a/src/Microsoft.TestPlatform.ObjectModel/Host/ITestRunTimeProvider.cs b/src/Microsoft.TestPlatform.ObjectModel/Host/ITestRunTimeProvider.cs index 2a1860b014..b5f5ac9e9f 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/Host/ITestRunTimeProvider.cs +++ b/src/Microsoft.TestPlatform.ObjectModel/Host/ITestRunTimeProvider.cs @@ -83,7 +83,7 @@ public interface ITestRuntimeProvider /// /// List of test sources. /// List of paths to extension assemblies. - IEnumerable GetTestPlatformExtensions(IEnumerable sources, IEnumerable defaultExtensions); + IEnumerable GetTestPlatformExtensions(IEnumerable sources, IEnumerable extensions); } /// diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs index 8cb5317f67..ef1231136a 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs @@ -193,9 +193,9 @@ public virtual TestProcessStartInfo GetTestHostProcessStartInfo( } /// - public IEnumerable GetTestPlatformExtensions(IEnumerable sources, IEnumerable defaultExtensions) + public IEnumerable GetTestPlatformExtensions(IEnumerable sources, IEnumerable extensions) { - return defaultExtensions; + return extensions; } /// diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs index dbde0d1e49..d9514ddba0 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs @@ -277,7 +277,7 @@ public virtual TestProcessStartInfo GetTestHostProcessStartInfo( } /// - public IEnumerable GetTestPlatformExtensions(IEnumerable sources, IEnumerable defaultExtensions) + public IEnumerable GetTestPlatformExtensions(IEnumerable sources, IEnumerable extensions) { var sourceDirectory = Path.GetDirectoryName(sources.Single()); diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Microsoft.TestPlatform.TestHostProvider.csproj b/src/Microsoft.TestPlatform.TestHostProvider/Microsoft.TestPlatform.TestHostProvider.csproj index 3d8d75f090..8e03cd39e7 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Microsoft.TestPlatform.TestHostProvider.csproj +++ b/src/Microsoft.TestPlatform.TestHostProvider/Microsoft.TestPlatform.TestHostProvider.csproj @@ -1,55 +1,55 @@ - - - - ..\..\ - - - - Microsoft.TestPlatform.TestHostRuntimeProvider - netstandard1.5;net46 - true - - - - - - - true - - - - - - - - 1.0.3 - - - - - 4.3.0 - - - - - - - - - - True - True - Resources.resx - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - Microsoft.TestPlatform.TestHostProvider - - - + + + + ..\..\ + + + + Microsoft.TestPlatform.TestHostRuntimeProvider + netstandard1.5;net46 + true + + + + + + + true + + + + + + + + 1.0.3 + + + + + 4.3.0 + + + + + + + + + + True + True + Resources.resx + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + Microsoft.TestPlatform.TestHostProvider + + + \ No newline at end of file diff --git a/src/vstest.console/CommandLine/Executor.cs b/src/vstest.console/CommandLine/Executor.cs index 58307fb073..89e6b00e18 100644 --- a/src/vstest.console/CommandLine/Executor.cs +++ b/src/vstest.console/CommandLine/Executor.cs @@ -344,4 +344,4 @@ private void PrintSplashScreen() #endregion } -} +} \ No newline at end of file diff --git a/src/vstest.console/Processors/TestAdapterPathArgumentProcessor.cs b/src/vstest.console/Processors/TestAdapterPathArgumentProcessor.cs index 412be79fe2..a01bee850b 100644 --- a/src/vstest.console/Processors/TestAdapterPathArgumentProcessor.cs +++ b/src/vstest.console/Processors/TestAdapterPathArgumentProcessor.cs @@ -10,13 +10,15 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors using System.IO; using System.Linq; + using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; using Microsoft.VisualStudio.TestPlatform.Common; - using Microsoft.VisualStudio.TestPlatform.Client; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; + using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; using Microsoft.VisualStudio.TestPlatform.Utilities; - using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; + + using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; + /// /// Allows the user to specify a path to load custom adapters from. /// @@ -60,7 +62,7 @@ public Lazy Executor { if (this.executor == null) { - this.executor = new Lazy(() => new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, TestPlatformFactory.GetTestPlatform(), ConsoleOutput.Instance, new FileHelper())); + this.executor = new Lazy(() => new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, ConsoleOutput.Instance, new FileHelper())); } return this.executor; @@ -84,7 +86,7 @@ internal class TestAdapterPathArgumentProcessorCapabilities : BaseArgumentProces public override bool IsAction => false; - public override ArgumentProcessorPriority Priority => ArgumentProcessorPriority.TestAdapterPath; + public override ArgumentProcessorPriority Priority => ArgumentProcessorPriority.AutoUpdateRunSettings; public override string HelpContentResourceName => CommandLineResources.TestAdapterPathHelp; @@ -104,9 +106,9 @@ internal class TestAdapterPathArgumentExecutor : IArgumentExecutor private CommandLineOptions commandLineOptions; /// - /// The test platform instance. + /// Run settings provider. /// - private ITestPlatform testPlatform; + private IRunSettingsProvider runSettingsManager; /// /// Used for sending output. @@ -127,12 +129,12 @@ internal class TestAdapterPathArgumentExecutor : IArgumentExecutor /// /// The options. /// The test platform - public TestAdapterPathArgumentExecutor(CommandLineOptions options, ITestPlatform testPlatform, IOutput output, IFileHelper fileHelper) + public TestAdapterPathArgumentExecutor(CommandLineOptions options, IRunSettingsProvider runSettingsManager, IOutput output, IFileHelper fileHelper) { Contract.Requires(options != null); this.commandLineOptions = options; - this.testPlatform = testPlatform; + this.runSettingsManager = runSettingsManager; this.output = output; this.fileHelper = fileHelper; } @@ -165,6 +167,35 @@ public void Initialize(string argument) { throw new DirectoryNotFoundException(CommandLineResources.TestAdapterPathDoesNotExist); } + + // Get testadapter paths from RunSettings. + var testAdapterPathsInRunSettings = this.runSettingsManager.QueryRunSettingsNode("RunConfiguration.TestAdaptersPaths"); + + if (!string.IsNullOrWhiteSpace(testAdapterPathsInRunSettings)) + { + var testAdapterFullPaths = new List(); + var testAdapterPathsInRunSettingsArray = testAdapterPathsInRunSettings.Split( + new[] { ';' }, + StringSplitOptions.RemoveEmptyEntries); + + foreach (var testadapterPath in testAdapterPathsInRunSettingsArray) + { + var testAdapterFullPath = Path.GetFullPath(testadapterPath); + + if (!this.fileHelper.DirectoryExists(testAdapterFullPath)) + { + throw new DirectoryNotFoundException(CommandLineResources.TestAdapterPathDoesNotExist); + } + + testAdapterFullPaths.Add(testAdapterFullPath); + } + + testAdapterFullPaths.Add(customAdaptersPath); + testAdapterFullPaths = testAdapterFullPaths.Distinct().ToList(); + customAdaptersPath = string.Join(";", testAdapterFullPaths.ToArray()); + } + + this.runSettingsManager.UpdateRunSettingsNode("RunConfiguration.TestAdaptersPaths", customAdaptersPath); } catch (Exception e) { @@ -173,18 +204,6 @@ public void Initialize(string argument) } this.commandLineOptions.TestAdapterPath = customAdaptersPath; - var adapterFiles = new List(this.GetTestAdaptersFromDirectory(customAdaptersPath)); - - if (adapterFiles.Count > 0) - { - this.testPlatform.UpdateExtensions(adapterFiles, false); - } - else - { - // Print a warning about not finding any test adapter in provided path... - this.output.Warning(CommandLineResources.NoAdaptersFoundInTestAdapterPath, argument); - this.output.WriteLine(string.Empty, OutputLevel.Information); - } } /// @@ -197,23 +216,6 @@ public ArgumentProcessorResult Execute() return ArgumentProcessorResult.Success; } - /// - /// Gets the test adapters and loggers from directory. - /// - /// The directory. - /// The list of test adapter and logger assemblies. - internal virtual IEnumerable GetTestAdaptersFromDirectory(string directory) - { - // TODO this code is DRY violation with TestPlatform.AddExtensionAssemblies, require cleanup. This argument processor - // should update the run settings. - var extensionAssemblies = new List(this.fileHelper.EnumerateFiles(directory, TestPlatformConstants.TestAdapterRegexPattern, SearchOption.AllDirectories)); - extensionAssemblies.AddRange(this.fileHelper.EnumerateFiles(directory, TestPlatformConstants.TestLoggerRegexPattern, SearchOption.AllDirectories)); - extensionAssemblies.AddRange(this.fileHelper.EnumerateFiles(directory, TestPlatformConstants.RunTimeRegexPattern, SearchOption.AllDirectories)); - extensionAssemblies.AddRange(this.fileHelper.EnumerateFiles(directory, TestPlatformConstants.SettingsProviderRegexPattern, SearchOption.AllDirectories)); - - return extensionAssemblies; - } - #endregion } -} +} \ No newline at end of file diff --git a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestExtensionManagerTests.cs b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestExtensionManagerTests.cs index 30fe22a227..85322f5d92 100644 --- a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestExtensionManagerTests.cs +++ b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestExtensionManagerTests.cs @@ -1,20 +1,20 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; -using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; -using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; -using Microsoft.VisualStudio.TestPlatform.Common.Logging; -using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; -using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - namespace TestPlatform.Common.UnitTests.ExtensionFramework { + using System; + using System.Collections.Generic; + + using Microsoft.VisualStudio.TestPlatform.Common; + using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; + using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; + using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; + using Microsoft.VisualStudio.TestPlatform.Common.Logging; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; + using Microsoft.VisualStudio.TestTools.UnitTesting; + [TestClass] public class TestExtensionManagerTests { @@ -29,11 +29,8 @@ public void Initialize() { TestPluginCacheTests.SetupMockExtensions(); messageLogger = TestSessionMessageLogger.Instance; - TestPluginManager.Instance.GetTestExtensions - (out unfilteredTestExtensions, out filteredTestExtensions); - - - + TestPluginManager.Instance.GetSpecificTestExtensions + (TestPlatformConstants.TestLoggerRegexPattern, out unfilteredTestExtensions, out filteredTestExtensions); } [TestCleanup] @@ -46,10 +43,10 @@ public void Cleanup() public void TestExtensionManagerConstructorShouldThrowExceptionIfMessageLoggerIsNull() { Assert.ThrowsException(() => - { - testExtensionManager = new DummyTestExtensionManager(unfilteredTestExtensions, filteredTestExtensions, null); - } - ); + { + testExtensionManager = new DummyTestExtensionManager(unfilteredTestExtensions, filteredTestExtensions, null); + } + ); } [TestMethod] @@ -69,10 +66,10 @@ public void TryGetTestExtensionShouldThrowExceptionWithNullUri() testExtensionManager = new DummyTestExtensionManager(unfilteredTestExtensions, filteredTestExtensions, messageLogger); TestPluginCacheTests.SetupMockAdditionalPathExtensions(); Assert.ThrowsException(() => - { - var result = testExtensionManager.TryGetTestExtension(default(Uri)); - } - ); + { + var result = testExtensionManager.TryGetTestExtension(default(Uri)); + } + ); } [TestMethod] @@ -100,6 +97,5 @@ internal class DummyTestExtensionManager : TestExtensionManager>> unfilteredTestExtensions, IEnumerable> testExtensions, IMessageLogger logger) : base(unfilteredTestExtensions, testExtensions, logger) { } - } } diff --git a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginCacheTests.cs b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginCacheTests.cs index 2bc44255f0..8a6ad3c8a8 100644 --- a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginCacheTests.cs +++ b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginCacheTests.cs @@ -9,10 +9,11 @@ namespace TestPlatform.Common.UnitTests.ExtensionFramework using System.Linq; using System.Reflection; + using Microsoft.VisualStudio.TestPlatform.Common; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; using Microsoft.VisualStudio.TestPlatform.Common.SettingsProvider; - using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -30,8 +31,11 @@ public TestPluginCacheTests() // Reset the singleton. TestPluginCache.Instance = null; this.mockFileHelper = new Mock(); - this.testablePluginCache = new TestableTestPluginCache(this.mockFileHelper.Object); - + this.testablePluginCache = new TestableTestPluginCache( + this.mockFileHelper.Object, + new List() { typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location }); + + this.mockFileHelper.Setup(fh => fh.DirectoryExists(It.IsAny())).Returns(true); } #region Properties tests @@ -42,12 +46,6 @@ public void InstanceShouldNotReturnANull() Assert.IsNotNull(TestPluginCache.Instance); } - [TestMethod] - public void AreExtensionsDiscoveredShouldBeFalseByDefault() - { - Assert.IsFalse(TestPluginCache.Instance.AreDefaultExtensionsDiscovered); - } - [TestMethod] public void TestExtensionsShouldBeNullByDefault() { @@ -57,7 +55,7 @@ public void TestExtensionsShouldBeNullByDefault() [TestMethod] public void PathToAdditionalExtensionsShouldBeNullByDefault() { - Assert.IsNull(TestPluginCache.Instance.PathToAdditionalExtensions); + Assert.IsNull(TestPluginCache.Instance.PathToExtensions); } [TestMethod] @@ -73,30 +71,30 @@ public void LoadOnlyWellKnownExtensionsShouldBeFalseByDefault() [TestMethod] public void UpdateAdditionalExtensionsShouldUpdateLoadOnlyWellKnownExtensions() { - TestPluginCache.Instance.UpdateAdditionalExtensions(null, true); + TestPluginCache.Instance.UpdateExtensions(null, true); Assert.IsTrue(TestPluginCache.Instance.LoadOnlyWellKnownExtensions); } [TestMethod] public void UpdateAdditionalExtensionsShouldNotThrowIfExtenionPathIsNull() { - TestPluginCache.Instance.UpdateAdditionalExtensions(null, true); - Assert.IsNull(TestPluginCache.Instance.PathToAdditionalExtensions); + TestPluginCache.Instance.UpdateExtensions(null, true); + Assert.IsNull(TestPluginCache.Instance.PathToExtensions); } [TestMethod] public void UpdateAdditionalExtensionsShouldNotThrowIfExtensionPathIsEmpty() { - TestPluginCache.Instance.UpdateAdditionalExtensions(new List(), true); - Assert.IsNull(TestPluginCache.Instance.PathToAdditionalExtensions); + TestPluginCache.Instance.UpdateExtensions(new List(), true); + Assert.IsNull(TestPluginCache.Instance.PathToExtensions); } [TestMethod] public void UpdateAdditionalExtensionsShouldUpdateAdditionalExtensions() { var additionalExtensions = new List { typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location }; - TestPluginCache.Instance.UpdateAdditionalExtensions(additionalExtensions, true); - var updatedExtensions = TestPluginCache.Instance.PathToAdditionalExtensions; + TestPluginCache.Instance.UpdateExtensions(additionalExtensions, true); + var updatedExtensions = TestPluginCache.Instance.PathToExtensions; Assert.IsNotNull(updatedExtensions); CollectionAssert.AreEqual(additionalExtensions, updatedExtensions.ToList()); @@ -110,8 +108,8 @@ public void UpdateAdditionalExtensionsShouldOnlyAddUniqueExtensionPaths() typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location, typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location }; - TestPluginCache.Instance.UpdateAdditionalExtensions(additionalExtensions, true); - var updatedExtensions = TestPluginCache.Instance.PathToAdditionalExtensions.ToList(); + TestPluginCache.Instance.UpdateExtensions(additionalExtensions, true); + var updatedExtensions = TestPluginCache.Instance.PathToExtensions.ToList(); Assert.IsNotNull(updatedExtensions); Assert.AreEqual(1, updatedExtensions.Count); @@ -122,17 +120,17 @@ public void UpdateAdditionalExtensionsShouldOnlyAddUniqueExtensionPaths() public void UpdateAdditionalExtensionsShouldUpdatePathsThatDoNotExist() { var additionalExtensions = new List { "foo.dll" }; - TestPluginCache.Instance.UpdateAdditionalExtensions(additionalExtensions, true); - var updatedExtensions = TestPluginCache.Instance.PathToAdditionalExtensions; + TestPluginCache.Instance.UpdateExtensions(additionalExtensions, true); + var updatedExtensions = TestPluginCache.Instance.PathToExtensions; Assert.IsNotNull(updatedExtensions); Assert.AreEqual(1, updatedExtensions.Count()); } + [Ignore] [TestMethod] public void UpdateAdditionalExtensionsShouldResetExtensionsDiscoveredFlag() { - } #endregion @@ -143,26 +141,21 @@ public void UpdateAdditionalExtensionsShouldResetExtensionsDiscoveredFlag() public void GetDefaultResolutionPathsShouldReturnCurrentDirectoryByDefault() { var currentDirectory = Path.GetDirectoryName(typeof(TestPluginCache).GetTypeInfo().Assembly.Location); - var defaultExtensionsDirectory = Path.Combine(currentDirectory, "Extensions"); var expectedDirectories = new List { currentDirectory }; - if (Directory.Exists(defaultExtensionsDirectory)) - { - expectedDirectories.Add(defaultExtensionsDirectory); - } var resolutionPaths = TestPluginCache.Instance.GetDefaultResolutionPaths(); Assert.IsNotNull(resolutionPaths); CollectionAssert.AreEqual(expectedDirectories, resolutionPaths.ToList()); } - + [TestMethod] public void GetDefaultResolutionPathsShouldReturnAdditionalExtensionPathsDirectories() { var currentDirectory = Path.GetDirectoryName(typeof(TestPluginCache).GetTypeInfo().Assembly.Location); var candidateDirectory = Directory.GetParent(currentDirectory).FullName; var extensionPaths = new List { Path.Combine(candidateDirectory, "foo.dll") }; - + // Setup mocks. var mockFileHelper = new Mock(); mockFileHelper.Setup(fh => fh.DirectoryExists(It.IsAny())).Returns(false); @@ -170,9 +163,9 @@ public void GetDefaultResolutionPathsShouldReturnAdditionalExtensionPathsDirecto TestPluginCache.Instance = testableTestPluginCache; - TestPluginCache.Instance.UpdateAdditionalExtensions(extensionPaths, true); + TestPluginCache.Instance.UpdateExtensions(extensionPaths, true); var resolutionPaths = TestPluginCache.Instance.GetDefaultResolutionPaths(); - + var expectedExtensions = new List { candidateDirectory, currentDirectory }; Assert.IsNotNull(resolutionPaths); @@ -191,7 +184,7 @@ public void GetDefaultResolutionPathsShouldReturnDirectoryFromDefaultExtensionsP var resolutionPaths = TestPluginCache.Instance.GetDefaultResolutionPaths(); Assert.IsNotNull(resolutionPaths); - CollectionAssert.AreEqual(new List { Path.GetDirectoryName(defaultExtensionsFile) }, resolutionPaths.ToList()); + Assert.IsTrue(resolutionPaths.Contains(Path.GetDirectoryName(defaultExtensionsFile))); } #endregion @@ -221,7 +214,7 @@ public void GetResolutionPathsShouldNotHaveDuplicatePathsIfExtensionIsInSameDire var tpCommonlocation = typeof(TestPluginCache).GetTypeInfo().Assembly.Location; var resolutionPaths = TestPluginCache.Instance.GetResolutionPaths(tpCommonlocation); - + var expectedPaths = new List { Path.GetDirectoryName(tpCommonlocation) }; CollectionAssert.AreEqual(expectedPaths, resolutionPaths.ToList()); @@ -230,14 +223,14 @@ public void GetResolutionPathsShouldNotHaveDuplicatePathsIfExtensionIsInSameDire #endregion #region GetTestExtensions tests - + [TestMethod] public void GetTestExtensionsShouldReturnExtensionsInAssembly() { SetupMockAdditionalPathExtensions(); - TestPluginCache.Instance.GetTestExtensions(typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location); - + TestPluginCache.Instance.GetTestExtensions(typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location); + Assert.IsNotNull(TestPluginCache.Instance.TestExtensions); Assert.IsTrue(TestPluginCache.Instance.TestExtensions.TestDiscoverers.Count > 0); } @@ -245,158 +238,50 @@ public void GetTestExtensionsShouldReturnExtensionsInAssembly() [TestMethod] public void GetTestExtensionsShouldAddTestExtensionsDiscoveredToCache() { - // Setup mocks. - var testExtensions = new TestExtensions(); - testExtensions.TestDiscoverers = new Dictionary(); - testExtensions.TestDiscoverers.Add("td", new TestDiscovererPluginInformation(typeof(TestPluginCacheTests))); - var extensionAssembly = typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location; - this.testablePluginCache.TestExtensionsSetter = (IEnumerable extensionAssemblies) => - { - if (extensionAssemblies.Count() == 1 && extensionAssemblies.ToArray()[0] == extensionAssembly) - { - return testExtensions; - } - return null; - }; - - this.testablePluginCache.GetTestExtensions(extensionAssembly); + var testDiscovererPluginInfos = this.testablePluginCache.GetTestExtensions(extensionAssembly); CollectionAssert.AreEqual( - testExtensions.TestDiscoverers.Keys, - this.testablePluginCache.TestExtensions.TestDiscoverers.Keys); + this.testablePluginCache.TestExtensions.TestDiscoverers.Keys, + testDiscovererPluginInfos.Keys); } [TestMethod] public void GetTestExtensionsShouldGetTestExtensionsFromCache() { - // Setup mocks. - var testExtensions = new TestExtensions(); - testExtensions.TestDiscoverers = new Dictionary(); - testExtensions.TestDiscoverers.Add("td", new TestDiscovererPluginInformation(typeof(TestPluginCacheTests))); - var extensionAssembly = typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location; - var callCount = 0; - - this.testablePluginCache.TestExtensionsSetter = (IEnumerable extensionAssemblies) => - { - if (extensionAssemblies.Count() == 1 && extensionAssemblies.ToArray()[0] == extensionAssembly) - { - callCount++; - return testExtensions; - } - return null; - }; + var testDiscovererPluginInfos = this.testablePluginCache.GetTestExtensions(extensionAssembly); + Assert.IsFalse(testDiscovererPluginInfos.ContainsKey("td")); - this.testablePluginCache.GetTestExtensions(extensionAssembly); + // Set the cache. + this.testablePluginCache.TestExtensions.TestDiscoverers.Add("td", new TestDiscovererPluginInformation(typeof(TestPluginCacheTests))); - this.testablePluginCache.GetTestExtensions(extensionAssembly); - - Assert.AreEqual(1, callCount); - } - - [TestMethod] - public void GetTestExtensionsShouldAddTestExtensionsToExistingCache() - { - // Setup mocks. - var testExtensions = new TestExtensions[2]; - for (var i =0; i < 2; i++) - { - testExtensions[i] = new TestExtensions(); - testExtensions[i].TestDiscoverers = new Dictionary(); - testExtensions[i].TestDiscoverers.Add("td" + i, new TestDiscovererPluginInformation(typeof(TestPluginCacheTests))); - } - - this.testablePluginCache.TestExtensionsSetter = (IEnumerable extensionAssemblies) => - { - if (extensionAssemblies.Count() == 1 && string.Equals(extensionAssemblies.ToArray()[0], "foo1.dll")) - { - return testExtensions[0]; - } - else if (extensionAssemblies.Count() == 1 && string.Equals(extensionAssemblies.ToArray()[0], "foo2.dll")) - { - return testExtensions[1]; - } - - return null; - }; - - var extensions1 = this.testablePluginCache.GetTestExtensions("foo1.dll"); - - var extensions2 = this.testablePluginCache.GetTestExtensions("foo2.dll"); - - // Validate if the inidividual extension are returned appropriately. - CollectionAssert.AreEqual(testExtensions[0].TestDiscoverers.Keys, extensions1.TestDiscoverers.Keys); - CollectionAssert.AreEqual(testExtensions[1].TestDiscoverers.Keys, extensions2.TestDiscoverers.Keys); - - var expectedDiscoverers = new Dictionary(); - expectedDiscoverers.Add("td0" , new TestDiscovererPluginInformation(typeof(TestPluginCacheTests))); - expectedDiscoverers.Add("td1", new TestDiscovererPluginInformation(typeof(TestPluginCacheTests))); - - CollectionAssert.AreEqual( - expectedDiscoverers.Keys, - this.testablePluginCache.TestExtensions.TestDiscoverers.Keys); + testDiscovererPluginInfos = this.testablePluginCache.GetTestExtensions(extensionAssembly); + Assert.IsTrue(testDiscovererPluginInfos.ContainsKey("td")); } + [Ignore] [TestMethod] public void GetTestExtensionsShouldShouldThrowIfDiscovererThrows() { - // Setup mocks. - var testExtensions = new TestExtensions(); - testExtensions.TestDiscoverers = new Dictionary(); - testExtensions.TestDiscoverers.Add("td", new TestDiscovererPluginInformation(typeof(TestPluginCacheTests))); + //todo : make ITestDiscoverer interface and then mock it in order to make this test case pass. var extensionAssembly = typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location; - - this.testablePluginCache.TestExtensionsSetter = (IEnumerable extensionAssemblies) => - { throw new ArgumentException(); }; - - Assert.ThrowsException(() => this.testablePluginCache.GetTestExtensions(extensionAssembly)); + Assert.ThrowsException(() => this.testablePluginCache.GetTestExtensions(extensionAssembly)); } #endregion - #region DiscoverAllTestExtensions tests - - [TestMethod] - public void DiscoverAllTestExtensionsShouldSetPropertyAreDefaultExtensionsDiscoveredToTrue() - { - // Setup the testable instance. - TestPluginCache.Instance = this.testablePluginCache; - TestPluginCache.Instance.DefaultExtensionPaths = new List() { typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location }; - - Assert.IsFalse(TestPluginCache.Instance.AreDefaultExtensionsDiscovered); - - TestPluginCache.Instance.DiscoverAllTestExtensions(); - - Assert.IsTrue(TestPluginCache.Instance.AreDefaultExtensionsDiscovered); - } - - [TestMethod] - public void DiscoverAllTestExtensionsShouldDiscoverExtensionsFromDefaultExtensionsFolder() - { - // Setup the testable instance. - TestPluginCache.Instance = this.testablePluginCache; - TestPluginCache.Instance.DefaultExtensionPaths = new List() { typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location }; - - TestPluginCache.Instance.DiscoverAllTestExtensions(); - - Assert.IsTrue(TestPluginCache.Instance.AreDefaultExtensionsDiscovered); - Assert.IsNotNull(TestPluginCache.Instance.TestExtensions); - - // Validate the discoverers to be absolutely certain. - Assert.IsTrue(TestPluginCache.Instance.TestExtensions.TestDiscoverers.Count > 0); - } + #region DiscoverTestExtensions tests [TestMethod] - public void DiscoverAllTestExtensionsShouldDiscoverExtensionsFromAdditionalExtensionsFolder() + public void DiscoverTestExtensionsShouldDiscoverExtensionsFromExtensionsFolder() { SetupMockAdditionalPathExtensions(); - TestPluginCache.Instance.DiscoverAllTestExtensions(); + TestPluginCache.Instance.DiscoverTestExtensions(TestPlatformConstants.TestAdapterRegexPattern); - Assert.IsTrue(TestPluginCache.Instance.AreDefaultExtensionsDiscovered); Assert.IsNotNull(TestPluginCache.Instance.TestExtensions); // Validate the discoverers to be absolutely certain. @@ -404,35 +289,14 @@ public void DiscoverAllTestExtensionsShouldDiscoverExtensionsFromAdditionalExten } [TestMethod] - public void DiscoverAllTestExtensionsShouldAddToTheExtensionsAlreadyDiscovered() + public void DiscoverTestExtensionsShouldSetCachedBoolToTrue() { - // Setup mocks. - var testableTestPluginCache = SetupMockAdditionalPathExtensions(); - - var testExtensions = new TestExtensions(); - testExtensions.TestDiscoverers = new Dictionary(); - testExtensions.TestDiscoverers.Add("td", new TestDiscovererPluginInformation(typeof(TestPluginCacheTests))); - - var extensionAssembly = typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location; - - testableTestPluginCache.TestExtensionsSetter = (IEnumerable extensionAssemblies) => - { - if (extensionAssemblies.Count() == 1 && extensionAssemblies.ToArray()[0] == "foo.dll") - { - return testExtensions; - } - else - { - var discoverer = new TestPluginDiscoverer(); - return discoverer.GetTestExtensionsInformation(extensionAssemblies, loadOnlyWellKnownExtensions: false); - } - }; - - testableTestPluginCache.GetTestExtensions("foo.dll"); + SetupMockAdditionalPathExtensions(); - testableTestPluginCache.DiscoverAllTestExtensions(); + TestPluginCache.Instance.DiscoverTestExtensions(TestPlatformConstants.TestAdapterRegexPattern); - CollectionAssert.Contains(testableTestPluginCache.TestExtensions.TestDiscoverers.Keys, "td"); + Assert.IsTrue(TestPluginCache.Instance.TestExtensions.AreTestDiscoverersCached); + Assert.IsTrue(TestPluginCache.Instance.TestExtensions.AreTestExtensionsCached()); } #endregion @@ -455,28 +319,33 @@ public static TestableTestPluginCache SetupMockAdditionalPathExtensions(string[] // Stub the default extensions folder. mockFileHelper.Setup(fh => fh.DirectoryExists(It.IsAny())).Returns(false); - TestPluginCache.Instance.UpdateAdditionalExtensions(extensions, true); + TestPluginCache.Instance.UpdateExtensions(extensions, true); return testPluginCache; } - public static void SetupMockExtensions() + public static void SetupMockExtensions(Mock mockFileHelper = null) { - SetupMockExtensions(() => { }); + SetupMockExtensions(() => { }, mockFileHelper); } - public static void SetupMockExtensions(Action callback) + public static void SetupMockExtensions(Action callback, Mock mockFileHelper = null) { - SetupMockExtensions(new[] { typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location }, callback); + SetupMockExtensions(new[] { typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location }, callback, mockFileHelper); } - public static void SetupMockExtensions(string[] extensions, Action callback) + public static void SetupMockExtensions(string[] extensions, Action callback, Mock mockFileHelper = null) { // Setup mocks. - var mockFileHelper = new Mock(); - var testableTestPluginCache = new TestableTestPluginCache(mockFileHelper.Object); + if (mockFileHelper == null) + { + mockFileHelper = new Mock(); + } - testableTestPluginCache.DefaultExtensionPaths = extensions; + mockFileHelper.Setup(fh => fh.DirectoryExists(It.IsAny())).Returns(true); + + var testableTestPluginCache = new TestableTestPluginCache(mockFileHelper.Object, extensions.ToList()); + testableTestPluginCache.Action = callback; // Setup the testable instance. TestPluginCache.Instance = testableTestPluginCache; @@ -495,24 +364,26 @@ public static void ResetExtensionsCache() public class TestableTestPluginCache : TestPluginCache { - public TestableTestPluginCache(IFileHelper fileHelper) : base(fileHelper) + public Action Action; + public TestableTestPluginCache(IFileHelper fileHelper, List extensionsPath) : base(fileHelper) { + TestDiscoveryExtensionManager.Destroy(); + TestExecutorExtensionManager.Destroy(); + SettingsProviderExtensionManager.Destroy(); + this.UpdateExtensions(extensionsPath, true); } - - public Func, TestExtensions> TestExtensionsSetter { get; set; } - internal override TestExtensions GetTestExtensions(IEnumerable extensions) + public TestableTestPluginCache(IFileHelper fileHelper) : this(fileHelper, new List()) { - if (this.TestExtensionsSetter == null) - { - return base.GetTestExtensions(extensions); - } - else - { - return this.TestExtensionsSetter.Invoke(extensions); - } + } + + internal override List GetFilteredExtensions(List extensions, string searchPattern) + { + this.Action?.Invoke(); + return extensions; } } #endregion } + diff --git a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginDiscovererTests.cs b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginDiscovererTests.cs index 2f7ee93e99..398ffeedb9 100644 --- a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginDiscovererTests.cs +++ b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginDiscovererTests.cs @@ -33,7 +33,7 @@ public void GetTestExtensionsInformationShouldNotThrowOnALoadException() var pathToExtensions = new List { "foo.dll" }; // The below should not throw an exception. - Assert.IsNotNull(this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true)); + Assert.IsNotNull(this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true)); } [TestMethod] @@ -42,23 +42,9 @@ public void GetTestExtensionsInformationShouldNotConsiderAbstractClasses() var pathToExtensions = new List { typeof(TestPluginDiscovererTests).GetTypeInfo().Assembly.Location }; // The below should not throw an exception. - var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); + var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); var discovererPluginInformation = new TestDiscovererPluginInformation(typeof(AbstractTestDiscoverer)); - Assert.IsFalse(testExtensions.TestDiscoverers.ContainsKey(discovererPluginInformation.IdentifierData)); - } - - [TestMethod] - public void GetTestExtensionsInformationShouldNotListADiscovererExtensionAsAnotherExtensionType() - { - var pathToExtensions = new List { typeof(TestPluginDiscovererTests).GetTypeInfo().Assembly.Location }; - - // The below should not throw an exception. - var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); - var discovererPluginInformation = new TestDiscovererPluginInformation(typeof(ValidDiscoverer)); - - Assert.IsFalse(testExtensions.TestExecutors.ContainsKey(discovererPluginInformation.IdentifierData)); - Assert.IsFalse(testExtensions.TestLoggers.ContainsKey(discovererPluginInformation.IdentifierData)); - Assert.IsFalse(testExtensions.TestSettingsProviders.ContainsKey(discovererPluginInformation.IdentifierData)); + Assert.IsFalse(testExtensions.ContainsKey(discovererPluginInformation.IdentifierData)); } [TestMethod] @@ -67,13 +53,13 @@ public void GetTestExtensionsInformationShouldReturnDiscovererExtensions() var pathToExtensions = new List { typeof(TestPluginDiscovererTests).GetTypeInfo().Assembly.Location }; // The below should not throw an exception. - var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); + var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); var discovererPluginInformation = new TestDiscovererPluginInformation(typeof(ValidDiscoverer)); var discovererPluginInformation2 = new TestDiscovererPluginInformation(typeof(ValidDiscoverer2)); - Assert.IsTrue(testExtensions.TestDiscoverers.ContainsKey(discovererPluginInformation.IdentifierData)); - Assert.IsTrue(testExtensions.TestDiscoverers.ContainsKey(discovererPluginInformation2.IdentifierData)); + Assert.IsTrue(testExtensions.ContainsKey(discovererPluginInformation.IdentifierData)); + Assert.IsTrue(testExtensions.ContainsKey(discovererPluginInformation2.IdentifierData)); } [TestMethod] @@ -82,14 +68,14 @@ public void GetTestExtensionsInformationShouldReturnExecutorExtensions() var pathToExtensions = new List { typeof(TestPluginDiscovererTests).GetTypeInfo().Assembly.Location }; // The below should not throw an exception. - var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); + var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); var pluginInformation = new TestExecutorPluginInformation(typeof(ValidExecutor)); var pluginInformation2 = new TestExecutorPluginInformation(typeof(ValidExecutor2)); - Assert.AreEqual(2, testExtensions.TestExecutors.Keys.Where(k => k.Contains("ValidExecutor")).Count()); - Assert.IsTrue(testExtensions.TestExecutors.ContainsKey(pluginInformation.IdentifierData)); - Assert.IsTrue(testExtensions.TestExecutors.ContainsKey(pluginInformation2.IdentifierData)); + Assert.AreEqual(2, testExtensions.Keys.Count(k => k.Contains("ValidExecutor"))); + Assert.IsTrue(testExtensions.ContainsKey(pluginInformation.IdentifierData)); + Assert.IsTrue(testExtensions.ContainsKey(pluginInformation2.IdentifierData)); } [TestMethod] @@ -98,14 +84,14 @@ public void GetTestExtensionsInformationShouldReturnLoggerExtensions() var pathToExtensions = new List { typeof(TestPluginDiscovererTests).GetTypeInfo().Assembly.Location }; // The below should not throw an exception. - var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); + var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); var pluginInformation = new TestLoggerPluginInformation(typeof(ValidLogger)); var pluginInformation2 = new TestLoggerPluginInformation(typeof(ValidLogger2)); - Assert.AreEqual(1, testExtensions.TestLoggers.Keys.Where(k => k.Contains("csv")).Count()); - Assert.IsTrue(testExtensions.TestLoggers.ContainsKey(pluginInformation.IdentifierData)); - Assert.IsTrue(testExtensions.TestLoggers.ContainsKey(pluginInformation2.IdentifierData)); + Assert.AreEqual(1, testExtensions.Keys.Where(k => k.Contains("csv")).Count()); + Assert.IsTrue(testExtensions.ContainsKey(pluginInformation.IdentifierData)); + Assert.IsTrue(testExtensions.ContainsKey(pluginInformation2.IdentifierData)); } [TestMethod] @@ -114,14 +100,14 @@ public void GetTestExtensionsInformationShouldReturnSettingsProviderExtensions() var pathToExtensions = new List { typeof(TestPluginDiscovererTests).GetTypeInfo().Assembly.Location }; // The below should not throw an exception. - var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); + var testExtensions = this.testPluginDiscoverer.GetTestExtensionsInformation(pathToExtensions, loadOnlyWellKnownExtensions: true); var pluginInformation = new TestSettingsProviderPluginInformation(typeof(ValidSettingsProvider)); var pluginInformation2 = new TestSettingsProviderPluginInformation(typeof(ValidSettingsProvider2)); - Assert.IsTrue(testExtensions.TestSettingsProviders.Keys.Select(k => k.Contains("ValidSettingsProvider")).Count() >= 3); - Assert.IsTrue(testExtensions.TestSettingsProviders.ContainsKey(pluginInformation.IdentifierData)); - Assert.IsTrue(testExtensions.TestSettingsProviders.ContainsKey(pluginInformation2.IdentifierData)); + Assert.IsTrue(testExtensions.Keys.Select(k => k.Contains("ValidSettingsProvider")).Count() >= 3); + Assert.IsTrue(testExtensions.ContainsKey(pluginInformation.IdentifierData)); + Assert.IsTrue(testExtensions.ContainsKey(pluginInformation2.IdentifierData)); } #region implementations @@ -143,7 +129,7 @@ public void DiscoverTests(IEnumerable sources, IDiscoveryContext discove throw new NotImplementedException(); } } - + private class ValidDiscoverer2 : ITestDiscoverer { public void DiscoverTests(IEnumerable sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink) diff --git a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginManagerTests.cs b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginManagerTests.cs index 155faafe36..137a0ced0f 100644 --- a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginManagerTests.cs +++ b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/TestPluginManagerTests.cs @@ -4,21 +4,24 @@ namespace TestPlatform.Common.UnitTests.ExtensionFramework { using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Reflection; + using Microsoft.VisualStudio.TestPlatform.Common; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; - using System.Collections.Generic; - using Microsoft.VisualStudio.TestPlatform.ObjectModel; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; + using Microsoft.VisualStudio.TestPlatform.ObjectModel; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; + using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; + using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; - using Microsoft.VisualStudio.TestPlatform.Common.Utilities; - using System.Reflection; - using System.Linq; + [TestClass] public class TestPluginManagerTests { @@ -64,7 +67,7 @@ public void InstanceShouldReturnTestPluginManagerInstance() public void InstanceShouldReturnCachedTestPluginManagerInstance() { var instance = TestPluginManager.Instance; - + Assert.AreEqual(instance, TestPluginManager.Instance); } @@ -76,15 +79,42 @@ public void GetTestExtensionsShouldReturnTestDiscovererExtensions() IEnumerable>> unfilteredTestExtensions; IEnumerable> testExtensions; - TestPluginManager.Instance.GetTestExtensions( - out unfilteredTestExtensions, - out testExtensions); + TestPluginManager.Instance.GetSpecificTestExtensions( + TestPlatformConstants.TestAdapterRegexPattern, + out unfilteredTestExtensions, + out testExtensions); Assert.IsNotNull(unfilteredTestExtensions); Assert.IsNotNull(testExtensions); Assert.IsTrue(testExtensions.Count() > 0); } + [TestMethod] + public void GetTestExtensionsShouldDiscoverExtensionsOnlyOnce() + { + var discoveryCount = 0; + TestPluginCacheTests.SetupMockExtensions(() => { discoveryCount++; }); + + IEnumerable>> unfilteredTestExtensions; + IEnumerable> testExtensions; + + TestPluginManager.Instance.GetSpecificTestExtensions( + TestPlatformConstants.TestAdapterRegexPattern, + out unfilteredTestExtensions, + out testExtensions); + + // Call this again to verify that discovery is not called again. + TestPluginManager.Instance.GetSpecificTestExtensions( + TestPlatformConstants.TestAdapterRegexPattern, + out unfilteredTestExtensions, + out testExtensions); + + Assert.IsNotNull(testExtensions); + Assert.IsTrue(testExtensions.Count() > 0); + + Assert.AreEqual(1, discoveryCount); + } + [TestMethod] public void GetTestExtensionsForAnExtensionAssemblyShouldReturnExtensionsInThatAssembly() { @@ -92,7 +122,7 @@ public void GetTestExtensionsForAnExtensionAssemblyShouldReturnExtensionsInThatA IEnumerable> testExtensions; TestPluginManager.Instance - .GetTestExtensions( + .GetTestExtensions( typeof(TestPluginManagerTests).GetTypeInfo().Assembly.Location, out unfilteredTestExtensions, out testExtensions); diff --git a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/Utilities/TestExtensionsTests.cs b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/Utilities/TestExtensionsTests.cs index 6eff2732cb..4525781aca 100644 --- a/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/Utilities/TestExtensionsTests.cs +++ b/test/Microsoft.TestPlatform.Common.UnitTests/ExtensionFramework/Utilities/TestExtensionsTests.cs @@ -23,7 +23,7 @@ public void TestInit() [TestMethod] public void AddExtensionsShouldNotThrowIfExtensionsIsNull() { - this.testExtensions.AddExtensions(null); + this.testExtensions.AddExtension(null); // Validate that the default state does not change. Assert.IsNull(this.testExtensions.TestDiscoverers); @@ -32,18 +32,16 @@ public void AddExtensionsShouldNotThrowIfExtensionsIsNull() [TestMethod] public void AddExtensionsShouldNotThrowIfExistingExtensionCollectionIsNull() { - var newTestExtensions = new TestExtensions(); - newTestExtensions.TestDiscoverers = - new System.Collections.Generic.Dictionary(); + var testDiscoverers = new System.Collections.Generic.Dictionary(); - newTestExtensions.TestDiscoverers.Add( + testDiscoverers.Add( "td", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); - this.testExtensions.AddExtensions(newTestExtensions); - + this.testExtensions.AddExtension(testDiscoverers); + Assert.IsNotNull(this.testExtensions.TestDiscoverers); - CollectionAssert.AreEqual(this.testExtensions.TestDiscoverers, newTestExtensions.TestDiscoverers); + CollectionAssert.AreEqual(this.testExtensions.TestDiscoverers, testDiscoverers); // Validate that the others remain same. Assert.IsNull(this.testExtensions.TestExecutors); @@ -54,33 +52,23 @@ public void AddExtensionsShouldNotThrowIfExistingExtensionCollectionIsNull() [TestMethod] public void AddExtensionsShouldAddToExistingExtensionCollection() { - var newTestExtensions = new TestExtensions(); - newTestExtensions.TestDiscoverers = - new System.Collections.Generic.Dictionary(); - - newTestExtensions.TestDiscoverers.Add( - "td1", - new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); - newTestExtensions.TestDiscoverers.Add( - "td2", - new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); + var testDiscoverers = new System.Collections.Generic.Dictionary(); - this.testExtensions.TestDiscoverers = - new Dictionary(); + testDiscoverers.Add("td1", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); + testDiscoverers.Add("td2", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); - this.testExtensions.TestDiscoverers.Add( - "td", - new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); + this.testExtensions.TestDiscoverers = new Dictionary(); + this.testExtensions.TestDiscoverers.Add("td", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); // Act. - this.testExtensions.AddExtensions(newTestExtensions); + this.testExtensions.AddExtension(testDiscoverers); // Validate. var expectedTestExtensions = new Dictionary(); expectedTestExtensions.Add("td", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); expectedTestExtensions.Add("td1", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); expectedTestExtensions.Add("td2", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); - + CollectionAssert.AreEqual(this.testExtensions.TestDiscoverers.Keys, expectedTestExtensions.Keys); // Validate that the others remain same. @@ -92,26 +80,19 @@ public void AddExtensionsShouldAddToExistingExtensionCollection() [TestMethod] public void AddExtensionsShouldNotAddAnAlreadyExistingExtensionToTheCollection() { - var newTestExtensions = new TestExtensions(); - newTestExtensions.TestDiscoverers = - new System.Collections.Generic.Dictionary(); + var testDiscoverers = new System.Collections.Generic.Dictionary(); - newTestExtensions.TestDiscoverers.Add( - "td", - new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); + testDiscoverers.Add("td", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); - this.testExtensions.TestDiscoverers = - new System.Collections.Generic.Dictionary(); + this.testExtensions.TestDiscoverers = new System.Collections.Generic.Dictionary(); - this.testExtensions.TestDiscoverers.Add( - "td", - new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); + this.testExtensions.TestDiscoverers.Add("td", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); // Act. - this.testExtensions.AddExtensions(newTestExtensions); - + this.testExtensions.AddExtension(testDiscoverers); + // Validate. - CollectionAssert.AreEqual(this.testExtensions.TestDiscoverers.Keys, newTestExtensions.TestDiscoverers.Keys); + CollectionAssert.AreEqual(this.testExtensions.TestDiscoverers.Keys, testDiscoverers.Keys); // Validate that the others remain same. Assert.IsNull(this.testExtensions.TestExecutors); @@ -119,30 +100,6 @@ public void AddExtensionsShouldNotAddAnAlreadyExistingExtensionToTheCollection() Assert.IsNull(this.testExtensions.TestLoggers); } - [TestMethod] - public void AddExtensionsShouldAddAllExtensions() - { - var newTestExtensions = new TestExtensions(); - newTestExtensions.TestDiscoverers = new Dictionary(); - newTestExtensions.TestExecutors = new Dictionary(); - newTestExtensions.TestSettingsProviders = new Dictionary(); - newTestExtensions.TestLoggers = new Dictionary(); - - newTestExtensions.TestDiscoverers.Add("td", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); - newTestExtensions.TestExecutors.Add("te", new TestExecutorPluginInformation(typeof(TestExtensionsTests))); - newTestExtensions.TestSettingsProviders.Add("tsp", new TestSettingsProviderPluginInformation(typeof(TestExtensionsTests))); - newTestExtensions.TestLoggers.Add("tl", new TestLoggerPluginInformation(typeof(TestExtensionsTests))); - - // Act. - this.testExtensions.AddExtensions(newTestExtensions); - - // Validate. - CollectionAssert.AreEqual(this.testExtensions.TestDiscoverers.Keys, newTestExtensions.TestDiscoverers.Keys); - CollectionAssert.AreEqual(this.testExtensions.TestExecutors.Keys, newTestExtensions.TestExecutors.Keys); - CollectionAssert.AreEqual(this.testExtensions.TestSettingsProviders.Keys, newTestExtensions.TestSettingsProviders.Keys); - CollectionAssert.AreEqual(this.testExtensions.TestLoggers.Keys, newTestExtensions.TestLoggers.Keys); - } - [TestMethod] public void GetExtensionsDiscoveredFromAssemblyShouldReturnNullIfNoExtensionsPresent() { @@ -155,7 +112,7 @@ public void GetExtensionsDiscoveredFromAssemblyShouldReturnNullIfNoExtensionsPre public void GetExtensionsDiscoveredFromAssemblyShouldNotThrowIfExtensionAssemblyIsNull() { this.testExtensions.TestDiscoverers = new Dictionary(); - + this.testExtensions.TestDiscoverers.Add("td", new TestDiscovererPluginInformation(typeof(TestExtensionsTests))); Assert.IsNull(this.testExtensions.GetExtensionsDiscoveredFromAssembly(null)); @@ -247,4 +204,4 @@ public void GetExtensionsDiscoveredFromAssemblyShouldReturnTestDiscoveresAndLogg CollectionAssert.AreEqual(expectedLoggers.Keys, extensions.TestLoggers.Keys); } } -} +} \ No newline at end of file diff --git a/test/Microsoft.TestPlatform.Common.UnitTests/Hosting/TestHostProviderManagerTests.cs b/test/Microsoft.TestPlatform.Common.UnitTests/Hosting/TestHostProviderManagerTests.cs index a3d2b76e35..3ad27066d4 100644 --- a/test/Microsoft.TestPlatform.Common.UnitTests/Hosting/TestHostProviderManagerTests.cs +++ b/test/Microsoft.TestPlatform.Common.UnitTests/Hosting/TestHostProviderManagerTests.cs @@ -177,7 +177,7 @@ public TestProcessStartInfo GetTestHostProcessStartInfo(IEnumerable sour throw new NotImplementedException(); } - public IEnumerable GetTestPlatformExtensions(IEnumerable sources, IEnumerable defaultExtensions) + public IEnumerable GetTestPlatformExtensions(IEnumerable sources, IEnumerable extensions) { throw new NotImplementedException(); } @@ -256,7 +256,7 @@ public TestProcessStartInfo GetTestHostProcessStartInfo(IEnumerable sour throw new NotImplementedException(); } - public IEnumerable GetTestPlatformExtensions(IEnumerable sources, IEnumerable defaultExtensions) + public IEnumerable GetTestPlatformExtensions(IEnumerable sources, IEnumerable extensions) { throw new NotImplementedException(); } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs index f6cad96884..c822d43f67 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs @@ -67,11 +67,12 @@ public void InitializeShouldInitializeExtensionsIfPresent() try { - var extensions = new[] { "c:\\e1.TestAdapter.dll", "c:\\e2.TestAdapter.dll" }; + var extensions = new[] { "c:\\e1.dll", "c:\\e2.dll" }; // Setup Mocks. TestPluginCacheTests.SetupMockAdditionalPathExtensions(extensions); this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "c:\\e1.dll", "c:\\e2.dll" }); this.testDiscoveryManager.Initialize(); @@ -93,13 +94,13 @@ public void InitializeShouldQueryTestHostManagerForExtensions() TestPluginCache.Instance = null; try { - TestPluginCacheTests.SetupMockAdditionalPathExtensions(new[] { "c:\\e1.TestAdapter.dll" }); + TestPluginCacheTests.SetupMockAdditionalPathExtensions(new[] { "c:\\e1.dll" }); this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); - this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "he1.dll" }); + this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "he1.dll", "c:\\e1.dll" }); this.testDiscoveryManager.Initialize(); - this.mockRequestSender.Verify(s => s.InitializeDiscovery(new[] { "he1.dll", "c:\\e1.TestAdapter.dll" }, true), Times.Once); + this.mockRequestSender.Verify(s => s.InitializeDiscovery(new[] { "he1.dll", "c:\\e1.dll" }, true), Times.Once); } finally { diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs index c275bbd58c..a76086a026 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs @@ -68,16 +68,16 @@ public void InitializeShouldInitializeExtensionsIfPresent() try { - var extensions = new[] { "c:\\e1.TestAdapter.dll", "c:\\e2.TestAdapter.dll" }; - TestPluginCacheTests.SetupMockAdditionalPathExtensions(extensions); + var extensions = new List() { "C:\\foo.dll" }; this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); - + this.mockTestHostManager.Setup(x => x.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())) + .Returns(extensions); this.testExecutionManager.Initialize(); // Also verify that we have waited for client connection. this.mockRequestSender.Verify(s => s.WaitForRequestHandlerConnection(It.IsAny()), Times.Once); this.mockRequestSender.Verify( - s => s.InitializeExecution(extensions, true), + s => s.InitializeExecution(extensions, false), Times.Once); } finally @@ -104,13 +104,12 @@ public void InitializeShouldQueryTestHostManagerForExtensions() TestPluginCache.Instance = null; try { - TestPluginCacheTests.SetupMockAdditionalPathExtensions(new[] { "c:\\e1.TestAdapter.dll" }); this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); - this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "he1.dll" }); + this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "he1.dll", "c:\\e1.dll" }); this.testExecutionManager.Initialize(); - this.mockRequestSender.Verify(s => s.InitializeExecution(new[] { "he1.dll", "c:\\e1.TestAdapter.dll" }, true), Times.Once); + this.mockRequestSender.Verify(s => s.InitializeExecution(new[] { "he1.dll", "c:\\e1.dll" }, false), Times.Once); } finally { @@ -145,9 +144,9 @@ public void StartTestRunShouldInitializeIfNotInitializedAlready() public void StartTestRunShouldInitializeExtensionsIfTestHostIsNotShared() { TestPluginCache.Instance = null; - TestPluginCacheTests.SetupMockAdditionalPathExtensions(new[] { "x.TestAdapter.dll" }); this.mockTestHostManager.SetupGet(th => th.Shared).Returns(false); this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "x.dll" }); this.testExecutionManager.StartTestRun(this.mockTestRunCriteria.Object, null); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs index fa59604d4c..7ad22ccbf9 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs @@ -63,12 +63,15 @@ public void TestInit() null, this.mockTestRunEventsHandler.Object, this.mockTestPlatformEventSource.Object); + + TestPluginCacheTests.SetupMockExtensions(new string[] { typeof(BaseRunTestsTests).GetTypeInfo().Assembly.Location }, () => { }); } [TestCleanup] public void Cleanup() { TestExecutorExtensionManager.Destroy(); + TestPluginCacheTests.ResetExtensionsCache(); } #region Constructor tests @@ -99,7 +102,7 @@ public void ConstructorShouldInitializeExecutorUrisThatRanTests() } #endregion - + #region RunTests tests [TestMethod] @@ -192,7 +195,7 @@ public void RunTestsShouldNotThrowIfExceptionIsAnArgumentException() [TestMethod] public void RunTestsShouldAbortIfExecutorUriExtensionMapIsNull() { - TestRunCompleteEventArgs receivedCompleteArgs = null; + TestRunCompleteEventArgs receivedCompleteArgs = null; // Setup mocks. this.runTestsInstance.GetExecutorUriExtensionMapCallback = (fh, rc) => { return null; }; @@ -223,7 +226,7 @@ public void RunTestsShouldAbortIfExecutorUriExtensionMapIsNull() [TestMethod] public void RunTestsShouldInvokeTheTestExecutorIfAdapterAssemblyIsKnown() { - var assemblyLocation = typeof (BaseRunTestsTests).GetTypeInfo().Assembly.Location; + var assemblyLocation = typeof(BaseRunTestsTests).GetTypeInfo().Assembly.Location; var executorUriExtensionMap = new List> { new Tuple(new Uri(BaseRunTestsExecutorUri), assemblyLocation) @@ -237,7 +240,7 @@ public void RunTestsShouldInvokeTheTestExecutorIfAdapterAssemblyIsKnown() { receivedExecutor = executor; }; - + this.runTestsInstance.RunTests(); Assert.IsNotNull(receivedExecutor); @@ -260,9 +263,6 @@ public void RunTestsShouldInvokeTheTestExecutorIfAdapterAssemblyIsUnknown() { receivedExecutor = executor; }; - TestPluginCacheTests.SetupMockExtensions( - new string[] { typeof(BaseRunTestsTests).GetTypeInfo().Assembly.Location }, - () => { }); this.runTestsInstance.RunTests(); @@ -274,7 +274,7 @@ public void RunTestsShouldInvokeTheTestExecutorIfAdapterAssemblyIsUnknown() public void RunTestsShouldInstrumentExecutionStart() { this.runTestsInstance.RunTests(); - + this.mockTestPlatformEventSource.Verify(x => x.ExecutionStart(), Times.Once); } @@ -284,8 +284,8 @@ public void RunTestsShouldInstrumentExecutionStop() this.SetupExecutorUriMock(); - this.runTestsInstance.RunTests(); - + this.runTestsInstance.RunTests(); + this.mockTestPlatformEventSource.Verify(x => x.ExecutionStop(It.IsAny()), Times.Once); } @@ -339,7 +339,7 @@ public void RunTestsShouldReportAWarningIfExecutorUriIsNotDefinedInExtensionAsse runtimeVersion); this.mockTestRunEventsHandler.Verify( treh => treh.HandleLogMessage(TestMessageLevel.Warning, expectedWarningMessage), Times.Once); - + // Should not have been called. Assert.IsNull(receivedExecutor); } @@ -355,7 +355,7 @@ public void RunTestsShouldNotAddExecutorUriToExecutorUriListIfNoTestsAreRun() // Setup mocks. this.runTestsInstance.GetExecutorUriExtensionMapCallback = (fh, rc) => { return executorUriExtensionMap; }; - + this.runTestsInstance.RunTests(); Assert.AreEqual(0, this.runTestsInstance.GetExecutorUrisThatRanTests.Count); @@ -382,7 +382,7 @@ public void RunTestsShouldAddExecutorUriToExecutorUriListIfExecutorHasRunTests() this.runTestsInstance.RunTests(); - var expectedUris = new string[] {BaseRunTestsExecutorUri.ToLower()}; + var expectedUris = new string[] { BaseRunTestsExecutorUri.ToLower() }; CollectionAssert.AreEqual(expectedUris, this.runTestsInstance.GetExecutorUrisThatRanTests.ToArray()); } @@ -607,9 +607,6 @@ private void SetupExecutorUriMock() { receivedExecutor = executor; }; - TestPluginCacheTests.SetupMockExtensions( - new string[] { typeof(BaseRunTestsTests).GetTypeInfo().Assembly.Location }, - () => { }); } #endregion @@ -634,7 +631,8 @@ public TestableBaseRunTests( public Action , Tuple, RunContext, - IFrameworkHandle> InvokeExecutorCallback { get; set; } + IFrameworkHandle> InvokeExecutorCallback + { get; set; } /// /// Gets the run settings. @@ -685,17 +683,17 @@ private class TestExecutor : ITestExecutor { public void Cancel() { - + } public void RunTests(IEnumerable sources, IRunContext runContext, IFrameworkHandle frameworkHandle) { - + } public void RunTests(IEnumerable tests, IRunContext runContext, IFrameworkHandle frameworkHandle) { - + } } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs index d1f2f4babf..34f4b6eb4e 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs @@ -10,9 +10,11 @@ namespace TestPlatform.CrossPlatEngine.UnitTests.Execution using Common.UnitTests.ExtensionFramework; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; + using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; using Microsoft.VisualStudio.TestPlatform.Common.SettingsProvider; using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; using Microsoft.VisualStudio.TestPlatform.ObjectModel; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol; @@ -20,6 +22,8 @@ namespace TestPlatform.CrossPlatEngine.UnitTests.Execution using Moq; + using TestPlatform.Common.UnitTests.Utilities; + using static RunTestsWithSourcesTests; [TestClass] @@ -49,8 +53,14 @@ public void TestCleanup() [TestMethod] public void InitializeShouldLoadAndInitializeAllExtension() { - var assemblyLocation = typeof(TestDiscoveryExtensionManagerTests).GetTypeInfo().Assembly.Location; - this.executionManager.Initialize(new List { assemblyLocation }); + var commonAssemblyLocation = typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location; + + TestPluginCacheTests.SetupMockExtensions( + new string[] { commonAssemblyLocation }, + () => { }); + + + this.executionManager.Initialize(new List { commonAssemblyLocation }); Assert.IsNotNull(TestPluginCache.Instance.TestExtensions); @@ -86,6 +96,12 @@ public void InitializeShouldLoadAndInitializeAllExtension() public void StartTestRunShouldRunTestsInTheProvidedSources() { var assemblyLocation = typeof(ExecutionManagerTests).GetTypeInfo().Assembly.Location; + TestPluginCacheTests.SetupMockExtensions( + new string[] { assemblyLocation }, + () => { }); + TestPluginCache.Instance.DiscoverTestExtensions(".*.TestAdapter.dll"); + TestPluginCache.Instance.DiscoverTestExtensions(".*.TestAdapter.dll"); + var adapterSourceMap = new Dictionary>(); adapterSourceMap.Add(assemblyLocation, new List { assemblyLocation }); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs index 817ef4a063..e827010d34 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/RunTestsWithSourcesTests.cs @@ -25,6 +25,8 @@ namespace TestPlatform.CrossPlatEngine.UnitTests.Execution using TestableImplementations; + using TestPlatform.Common.UnitTests.ExtensionFramework; + [TestClass] public class RunTestsWithSourcesTests { @@ -51,12 +53,19 @@ public void TestInit() isDebug: false, testCaseFilter: null); this.mockTestRunEventsHandler = new Mock(); + TestPluginCacheTests.SetupMockExtensions( + new string[] { typeof(RunTestsWithSourcesTests).GetTypeInfo().Assembly.Location }, + () => { }); + + TestPluginCache.Instance.DiscoverTestExtensions(".*.TestAdapter.dll"); + TestPluginCache.Instance.DiscoverTestExtensions(".*.TestAdapter.dll"); } [TestCleanup] public void TestCleanup() { RunTestWithSourcesExecutor.RunTestsWithSourcesCallback = null; + TestPluginCacheTests.ResetExtensionsCache(); } [TestMethod] diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestExtensionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestExtensionManagerTests.cs index 2088d61cb6..a0016fbb70 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestExtensionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestExtensionManagerTests.cs @@ -9,7 +9,6 @@ namespace TestPlatform.CrossPlatEngine.UnitTests using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; - using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -34,7 +33,7 @@ public void UseAdditionalExtensionsShouldUpdateAdditionalExtensionsInCache() this.testExtensionManager.UseAdditionalExtensions(extensions, true); Assert.IsTrue(TestPluginCache.Instance.LoadOnlyWellKnownExtensions); - CollectionAssert.AreEqual(extensions, TestPluginCache.Instance.PathToAdditionalExtensions.ToList()); + CollectionAssert.AreEqual(extensions, TestPluginCache.Instance.PathToExtensions.ToList()); } finally { diff --git a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs index a9c4876c11..8d9f56b80e 100644 --- a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs +++ b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs @@ -296,7 +296,7 @@ public void GetTestHostProcessStartInfoShouldIncludeSourceDirectoryAsWorkingDire public void GetTestPlatformExtensionsShouldReturnEmptySetIfSourceDirectoryDoesNotExist() { this.mockFileHelper.Setup(fh => fh.DirectoryExists(It.IsAny())).Returns(false); - var extensions = this.dotnetHostManager.GetTestPlatformExtensions(new[] { $".{Path.DirectorySeparatorChar}foo.dll" }, new List()); + var extensions = this.dotnetHostManager.GetTestPlatformExtensions(new[] { $".{Path.DirectorySeparatorChar}foo.dll" }, Enumerable.Empty()); Assert.AreEqual(0, extensions.Count()); } @@ -306,7 +306,7 @@ public void GetTestPlatformExtensionsShouldReturnLibariesFromSourceDirectory() { this.mockFileHelper.Setup(fh => fh.DirectoryExists(It.IsAny())).Returns(true); this.mockFileHelper.Setup(fh => fh.EnumerateFiles(It.IsAny(), It.IsAny(), SearchOption.TopDirectoryOnly)).Returns(new[] { "foo.TestAdapter.dll" }); - var extensions = this.dotnetHostManager.GetTestPlatformExtensions(new[] { $".{Path.DirectorySeparatorChar}foo.dll" }, new List()); + var extensions = this.dotnetHostManager.GetTestPlatformExtensions(new[] { $".{Path.DirectorySeparatorChar}foo.dll" }, Enumerable.Empty()); CollectionAssert.AreEqual(new[] { "foo.TestAdapter.dll" }, extensions.ToArray()); } @@ -317,7 +317,7 @@ public void GetTestPlatformExtensionsShouldReturnEmptySetIfSourceDirectoryIsEmpt // Parent directory is empty since the input source is file "test.dll" this.mockFileHelper.Setup(fh => fh.DirectoryExists(It.IsAny())).Returns(true); this.mockFileHelper.Setup(fh => fh.EnumerateFiles(It.IsAny(), It.IsAny(), SearchOption.TopDirectoryOnly)).Returns(new[] { "foo.dll" }); - var extensions = this.dotnetHostManager.GetTestPlatformExtensions(this.testSource, new List()); + var extensions = this.dotnetHostManager.GetTestPlatformExtensions(this.testSource, Enumerable.Empty()); Assert.AreEqual(0, extensions.Count()); } diff --git a/test/vstest.console.UnitTests/Processors/RunTestsArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/RunTestsArgumentProcessorTests.cs index d535fd501b..36eb94597c 100644 --- a/test/vstest.console.UnitTests/Processors/RunTestsArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/RunTestsArgumentProcessorTests.cs @@ -9,12 +9,12 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests.Processors using System.Reflection; using Microsoft.VisualStudio.TestPlatform.Client; + using Microsoft.VisualStudio.TestPlatform.Client.RequestHelper; using Microsoft.VisualStudio.TestPlatform.CommandLine.Internal; using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; using Microsoft.VisualStudio.TestPlatform.CommandLine.TestPlatformHelpers; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; - using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; using Microsoft.VisualStudio.TestPlatform.Common.Logging; using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing.Interfaces; using Microsoft.VisualStudio.TestPlatform.ObjectModel; @@ -23,11 +23,11 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests.Processors using Microsoft.VisualStudio.TestPlatform.Utilities; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; - using Microsoft.VisualStudio.TestPlatform.Client.RequestHelper; - using vstest.console.UnitTests.Processors; using Moq; + using vstest.console.UnitTests.Processors; + /// /// Tests for RunTestsArgumentProcessor /// @@ -311,20 +311,6 @@ public class TestableTestPluginCache : TestPluginCache public TestableTestPluginCache(IFileHelper fileHelper) : base(fileHelper) { } - - public Func, TestExtensions> TestExtensionsSetter { get; set; } - - internal override TestExtensions GetTestExtensions(IEnumerable extensions) - { - if (this.TestExtensionsSetter == null) - { - return base.GetTestExtensions(extensions); - } - else - { - return this.TestExtensionsSetter.Invoke(extensions); - } - } } #endregion diff --git a/test/vstest.console.UnitTests/Processors/TestAdapterPathArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/TestAdapterPathArgumentProcessorTests.cs index a5261e11df..ead870407b 100644 --- a/test/vstest.console.UnitTests/Processors/TestAdapterPathArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/TestAdapterPathArgumentProcessorTests.cs @@ -9,11 +9,14 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests.Processors using System.Reflection; using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; + using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; + using Microsoft.VisualStudio.TestPlatform.Common; + using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; using Microsoft.VisualStudio.TestPlatform.Utilities; - using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; + using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -45,7 +48,7 @@ public void CapabilitiesShouldReturnAppropriateProperties() Assert.AreEqual(HelpContentPriority.TestAdapterPathArgumentProcessorHelpPriority, capabilities.HelpPriority); Assert.AreEqual(false, capabilities.IsAction); - Assert.AreEqual(ArgumentProcessorPriority.TestAdapterPath, capabilities.Priority); + Assert.AreEqual(ArgumentProcessorPriority.AutoUpdateRunSettings, capabilities.Priority); Assert.AreEqual(false, capabilities.AllowMultiple); Assert.AreEqual(false, capabilities.AlwaysExecute); @@ -59,9 +62,9 @@ public void CapabilitiesShouldReturnAppropriateProperties() [TestMethod] public void InitializeShouldThrowIfArgumentIsNull() { - var mockTestPlatform = new Mock(); + var mockRunSettingsProvider = new Mock(); var mockOutput = new Mock(); - var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, mockTestPlatform.Object, mockOutput.Object, new FileHelper()); + var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, mockRunSettingsProvider.Object, mockOutput.Object, new FileHelper()); var message = @"The /TestAdapterPath parameter requires a value, which is path of a location containing custom test adapters. Example: /TestAdapterPath:c:\MyCustomAdapters"; @@ -85,9 +88,9 @@ public void InitializeShouldThrowIfArgumentIsNull() [TestMethod] public void InitializeShouldThrowIfArgumentIsAWhiteSpace() { - var mockTestPlatform = new Mock(); + var mockRunSettingsProvider = new Mock(); var mockOutput = new Mock(); - var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, mockTestPlatform.Object, mockOutput.Object, new FileHelper()); + var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, mockRunSettingsProvider.Object, mockOutput.Object, new FileHelper()); var message = @"The /TestAdapterPath parameter requires a value, which is path of a location containing custom test adapters. Example: /TestAdapterPath:c:\MyCustomAdapters"; @@ -111,9 +114,9 @@ public void InitializeShouldThrowIfArgumentIsAWhiteSpace() [TestMethod] public void InitializeShouldThrowIfPathDoesNotExist() { - var mockTestPlatform = new Mock(); + var mockRunSettingsProvider = new Mock(); var mockOutput = new Mock(); - var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, mockTestPlatform.Object, mockOutput.Object, new FileHelper()); + var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, mockRunSettingsProvider.Object, mockOutput.Object, new FileHelper()); var folder = "C:\\temp\\thisfolderdoesnotexist"; @@ -139,60 +142,71 @@ public void InitializeShouldThrowIfPathDoesNotExist() } [TestMethod] - public void InitializeShouldUpdateAdditionalExtensionsWithTestAdapterPath() + public void InitializeShouldUpdatTestAdapterPathInRunSettings() { - var mockTestPlatform = new Mock(); + RunSettingsManager.Instance.AddDefaultRunSettings(); + var mockOutput = new Mock(); - var executor = new TestableTestAdapterPathArgumentExecutor(CommandLineOptions.Instance, mockTestPlatform.Object, mockOutput.Object, new FileHelper()); + var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, new FileHelper()); var currentAssemblyPath = typeof(TestAdapterPathArgumentExecutor).GetTypeInfo().Assembly.Location; var currentFolder = Path.GetDirectoryName(currentAssemblyPath); - executor.TestAdapters = (directory) => - { - if (string.Equals(directory, currentFolder)) - { - return new List - { - typeof(TestAdapterPathArgumentExecutor).GetTypeInfo() - .Assembly.Location - }; - } + executor.Initialize(currentFolder); + var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(RunSettingsManager.Instance.ActiveRunSettings.SettingsXml); + Assert.AreEqual(currentFolder, runConfiguration.TestAdaptersPaths); + } + + [TestMethod] + public void InitializeShouldUpdatTestAdapterPathsInRunSettings() + { + RunSettingsManager.Instance.AddDefaultRunSettings(); - return new List { }; - }; + var mockOutput = new Mock(); + var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, new FileHelper()); + var currentAssemblyPath = typeof(TestAdapterPathArgumentExecutor).GetTypeInfo().Assembly.Location; + var currentFolder = Path.GetDirectoryName(currentAssemblyPath); executor.Initialize(currentFolder); - - mockTestPlatform.Verify(tp => tp.UpdateExtensions(new List { currentAssemblyPath }, false), Times.Once); + var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(RunSettingsManager.Instance.ActiveRunSettings.SettingsXml); + Assert.AreEqual(currentFolder, runConfiguration.TestAdaptersPaths); } [TestMethod] - public void InitializeShouldReportIfNoTestAdaptersFoundInPath() + public void InitializeShouldMergeTestAdapterPathsInRunSettings() { - var mockTestPlatform = new Mock(); + var runSettingsXml = "d:\\users;f:\\users"; + var runSettings = new RunSettings(); + runSettings.LoadSettingsXml(runSettingsXml); + RunSettingsManager.Instance.SetActiveRunSettings(runSettings); + var mockFileHelper = new Mock(); var mockOutput = new Mock(); - var executor = new TestableTestAdapterPathArgumentExecutor(CommandLineOptions.Instance, mockTestPlatform.Object, mockOutput.Object, new FileHelper()); - var currentAssemblyPath = typeof(TestAdapterPathArgumentExecutor).GetTypeInfo().Assembly.Location; - var currentFolder = Path.GetDirectoryName(currentAssemblyPath); + mockFileHelper.Setup(x => x.DirectoryExists(It.IsAny())).Returns(true); + var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, mockFileHelper.Object); - executor.TestAdapters = (directory) => - { - return new List { }; - }; + executor.Initialize("c:\\users"); + var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(RunSettingsManager.Instance.ActiveRunSettings.SettingsXml); + Assert.AreEqual("d:\\users;f:\\users;c:\\users", runConfiguration.TestAdaptersPaths); + } - executor.Initialize(currentFolder); + [TestMethod] + public void InitializeShouldMergeTestAdapterPathsInRunSettingsIgnoringDuplicatePaths() + { + var runSettingsXml = "d:\\users;c:\\users"; + var runSettings = new RunSettings(); + runSettings.LoadSettingsXml(runSettingsXml); + RunSettingsManager.Instance.SetActiveRunSettings(runSettings); + var mockFileHelper = new Mock(); + var mockOutput = new Mock(); - mockOutput.Verify( - o => - o.WriteLine( - string.Format( - "The path '{0}' specified in the 'TestAdapterPath' does not contain any test adapters, provide a valid path and try again.", - currentFolder), - OutputLevel.Warning)); + mockFileHelper.Setup(x => x.DirectoryExists(It.IsAny())).Returns(true); + var executor = new TestAdapterPathArgumentExecutor(CommandLineOptions.Instance, RunSettingsManager.Instance, mockOutput.Object, mockFileHelper.Object); + executor.Initialize("c:\\users"); + var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(RunSettingsManager.Instance.ActiveRunSettings.SettingsXml); + Assert.AreEqual("d:\\users;c:\\users", runConfiguration.TestAdaptersPaths); } #endregion @@ -201,23 +215,14 @@ public void InitializeShouldReportIfNoTestAdaptersFoundInPath() private class TestableTestAdapterPathArgumentExecutor : TestAdapterPathArgumentExecutor { - internal TestableTestAdapterPathArgumentExecutor(CommandLineOptions options, ITestPlatform testPlatform, IOutput output, IFileHelper fileHelper) - : base(options, testPlatform, output, fileHelper) + internal TestableTestAdapterPathArgumentExecutor(CommandLineOptions options, IRunSettingsProvider runSettingsProvider, IOutput output, IFileHelper fileHelper) + : base(options, runSettingsProvider, output, fileHelper) { } internal Func> TestAdapters { get; set; } - - internal override IEnumerable GetTestAdaptersFromDirectory(string directory) - { - if (this.TestAdapters != null) - { - return this.TestAdapters(directory); - } - return new List { }; - } } #endregion } -} +} \ No newline at end of file