Skip to content

Commit

Permalink
TestPluginCache and other dependencies refactoring (#2537)
Browse files Browse the repository at this point in the history
* Small improvements in TestPluginDiscoverer about loading types from assemblies

* Small performance improvements

* TestExtensions - refactored typeof operations

* Added new assembly level attribute to define excat types which should be loaded from that assembly.Removed unnecessary FileHelper instance.

* Commenting piece of code which cause build error

* Restored previous implementation

* Changed methods because previous changes had exception while building in CI

* Added missing attribute to blame, event collector and code coverage

* Redesigned custom attribute to specify interesting types themselves

* More improvements

* Fixed cast exception

* GetTypes returned to previous implementation and removed unncessary Stopwatch

* changed global.json

* returned to previous version in global.json

* PR review fix
  • Loading branch information
Sanan07 committed Nov 19, 2020
1 parent 2a3fd2c commit 67689ab
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 71 deletions.
Expand Up @@ -3,6 +3,8 @@

using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.TestPlatform.Extensions.EventLogCollector;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
Expand All @@ -12,6 +14,7 @@
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyProduct("Microsoft.TestPlatform.Extensions.EventLogCollector")]
[assembly: AssemblyTrademark("")]
[assembly: TypesToLoad(typeof(EventLogDataCollector))]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
Expand Down
Expand Up @@ -179,10 +179,10 @@ public List<string> GetExtensionPaths(string endsWithPattern, bool skipDefaultEx
this.TestExtensions = new TestExtensions();
}

this.TestExtensions.AddExtension<TPluginInfo>(pluginInfos);
this.TestExtensions.AddExtension(pluginInfos);

// Set the cache bool to true.
this.TestExtensions.SetTestExtensionsCacheStatus<TPluginInfo>();
this.TestExtensions.SetTestExtensionsCacheStatusToTrue<TPluginInfo>();

if (EqtTrace.IsVerboseEnabled)
{
Expand Down
Expand Up @@ -4,48 +4,35 @@
namespace Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System.Globalization;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;

using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities;
using Microsoft.VisualStudio.TestPlatform.Common.Logging;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;
using CommonResources = Microsoft.VisualStudio.TestPlatform.Common.Resources.Resources;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;
using CommonResources = Resources.Resources;

/// <summary>
/// Discovers test extensions in a directory.
/// </summary>
internal class TestPluginDiscoverer
{
private IFileHelper fileHelper;

private static List<string> UnloadableFiles = new List<string>();
private static HashSet<string> UnloadableFiles = new HashSet<string>();

/// <summary>
/// Initializes a new instance of the <see cref="TestPluginDiscoverer"/> class.
/// </summary>
public TestPluginDiscoverer() : this(new FileHelper())
public TestPluginDiscoverer()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="TestPluginDiscoverer"/> class.
/// </summary>
/// <param name="fileHelper">
/// The file Helper.
/// </param>
internal TestPluginDiscoverer(IFileHelper fileHelper)
{
this.fileHelper = fileHelper;
}

#region Fields

#if WINDOWS_UAP
Expand Down Expand Up @@ -176,11 +163,20 @@ private void AddKnownExtensions(ref IEnumerable<string> extensionPaths)
{
Debug.Assert(assembly != null, "null assembly");
Debug.Assert(pluginInfos != null, "null pluginInfos");
Type[] types;
IEnumerable<Type> types;
Type extension = typeof(TExtension);

try
{
types = assembly.GetTypes();
{
var customAttribute = CustomAttributeExtensions.GetCustomAttribute(assembly, typeof(TypesToLoadAttribute)) as TypesToLoadAttribute;
if (customAttribute != null)
{
types = customAttribute.Types;
}
else
{
types = assembly.GetTypes().Where(type => type.GetTypeInfo().IsClass && !type.GetTypeInfo().IsAbstract);
}
}
catch (ReflectionTypeLoadException e)
{
Expand All @@ -196,14 +192,11 @@ private void AddKnownExtensions(ref IEnumerable<string> extensionPaths)
return;
}

if ((types != null) && (types.Length > 0))
if (types != null && types.Any())
{
foreach (var type in types)
{
if (type.GetTypeInfo().IsClass && !type.GetTypeInfo().IsAbstract)
{
this.GetTestExtensionFromType(type, typeof(TExtension), pluginInfos);
}
GetTestExtensionFromType(type, extension, pluginInfos);
}
}
}
Expand Down Expand Up @@ -241,15 +234,14 @@ private void AddKnownExtensions(ref IEnumerable<string> extensionPaths)
EqtTrace.Error(
"TryGetTestExtensionFromType: Either PluginInformation is null or PluginInformation doesn't contain IdentifierData for type {0}.", type.FullName);
}

return;
}

if (extensionCollection.ContainsKey(pluginInfo.IdentifierData))
{
EqtTrace.Warning(
"TryGetTestExtensionFromType: Discovered multiple test extensions with identifier data '{0}'; keeping the first one.",
pluginInfo.IdentifierData);
"TryGetTestExtensionFromType: Discovered multiple test extensions with identifier data '{0}'; keeping the first one.",
pluginInfo.IdentifierData);
}
else
{
Expand Down
Expand Up @@ -5,6 +5,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;

using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities;
Expand Down
Expand Up @@ -147,31 +147,31 @@ internal TestExtensions GetExtensionsDiscoveredFromAssembly(string extensionAsse
var testExtensions = new TestExtensions();

testExtensions.TestDiscoverers =
this.GetExtensionsDiscoveredFromAssembly<TestDiscovererPluginInformation>(
this.GetExtensionsDiscoveredFromAssembly(
this.TestDiscoverers,
extensionAssembly);
testExtensions.TestExecutors =
this.GetExtensionsDiscoveredFromAssembly<TestExecutorPluginInformation>(
this.GetExtensionsDiscoveredFromAssembly(
this.TestExecutors,
extensionAssembly);
testExtensions.TestExecutors2 =
this.GetExtensionsDiscoveredFromAssembly<TestExecutorPluginInformation2>(
this.GetExtensionsDiscoveredFromAssembly(
this.TestExecutors2,
extensionAssembly);
testExtensions.TestSettingsProviders =
this.GetExtensionsDiscoveredFromAssembly<TestSettingsProviderPluginInformation>(
this.GetExtensionsDiscoveredFromAssembly(
this.TestSettingsProviders,
extensionAssembly);
testExtensions.TestLoggers =
this.GetExtensionsDiscoveredFromAssembly<TestLoggerPluginInformation>(
this.GetExtensionsDiscoveredFromAssembly(
this.TestLoggers,
extensionAssembly);
testExtensions.TestHosts =
this.GetExtensionsDiscoveredFromAssembly<TestRuntimePluginInformation>(
this.GetExtensionsDiscoveredFromAssembly(
this.TestHosts,
extensionAssembly);
testExtensions.DataCollectors =
this.GetExtensionsDiscoveredFromAssembly<DataCollectorConfig>(
this.GetExtensionsDiscoveredFromAssembly(
this.DataCollectors,
extensionAssembly);

Expand All @@ -192,31 +192,33 @@ internal TestExtensions GetExtensionsDiscoveredFromAssembly(string extensionAsse

internal Dictionary<string, TPluginInfo> GetTestExtensionCache<TPluginInfo>() where TPluginInfo : TestPluginInformation
{
if (typeof(TPluginInfo) == typeof(TestDiscovererPluginInformation))
Type type = typeof(TPluginInfo);

if (type == typeof(TestDiscovererPluginInformation))
{
return (Dictionary<string, TPluginInfo>)(object)this.TestDiscoverers;
}
else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation))
else if (type == typeof(TestExecutorPluginInformation))
{
return (Dictionary<string, TPluginInfo>)(object)this.TestExecutors;
}
else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation2))
else if (type == typeof(TestExecutorPluginInformation2))
{
return (Dictionary<string, TPluginInfo>)(object)this.TestExecutors2;
}
else if (typeof(TPluginInfo) == typeof(TestLoggerPluginInformation))
else if (type == typeof(TestLoggerPluginInformation))
{
return (Dictionary<string, TPluginInfo>)(object)this.TestLoggers;
}
else if (typeof(TPluginInfo) == typeof(TestSettingsProviderPluginInformation))
else if (type == typeof(TestSettingsProviderPluginInformation))
{
return (Dictionary<string, TPluginInfo>)(object)this.TestSettingsProviders;
}
else if (typeof(TPluginInfo) == typeof(TestRuntimePluginInformation))
else if (type == typeof(TestRuntimePluginInformation))
{
return (Dictionary<string, TPluginInfo>)(object)this.TestHosts;
}
else if (typeof(TPluginInfo) == typeof(DataCollectorConfig))
else if (type == typeof(DataCollectorConfig))
{
return (Dictionary<string, TPluginInfo>)(object)this.DataCollectors;
}
Expand All @@ -234,31 +236,33 @@ internal TestExtensions GetExtensionsDiscoveredFromAssembly(string extensionAsse
/// </returns>
internal bool AreTestExtensionsCached<TPluginInfo>() where TPluginInfo : TestPluginInformation
{
if (typeof(TPluginInfo) == typeof(TestDiscovererPluginInformation))
Type type = typeof(TPluginInfo);

if (type == typeof(TestDiscovererPluginInformation))
{
return this.AreTestDiscoverersCached;
}
else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation))
else if (type == typeof(TestExecutorPluginInformation))
{
return this.AreTestExecutorsCached;
}
else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation2))
else if (type == typeof(TestExecutorPluginInformation2))
{
return this.AreTestExecutors2Cached;
}
else if (typeof(TPluginInfo) == typeof(TestLoggerPluginInformation))
else if (type == typeof(TestLoggerPluginInformation))
{
return this.AreTestLoggersCached;
}
else if (typeof(TPluginInfo) == typeof(TestSettingsProviderPluginInformation))
else if (type == typeof(TestSettingsProviderPluginInformation))
{
return this.AreTestSettingsProvidersCached;
}
else if (typeof(TPluginInfo) == typeof(TestRuntimePluginInformation))
else if (type == typeof(TestRuntimePluginInformation))
{
return this.AreTestHostsCached;
}
else if (typeof(TPluginInfo) == typeof(DataCollectorConfig))
else if (type == typeof(DataCollectorConfig))
{
return this.AreDataCollectorsCached;
}
Expand All @@ -271,33 +275,35 @@ internal TestExtensions GetExtensionsDiscoveredFromAssembly(string extensionAsse
/// </summary>
/// <typeparam name="TPluginInfo">
/// </typeparam>
internal void SetTestExtensionsCacheStatus<TPluginInfo>() where TPluginInfo : TestPluginInformation
internal void SetTestExtensionsCacheStatusToTrue<TPluginInfo>() where TPluginInfo : TestPluginInformation
{
if (typeof(TPluginInfo) == typeof(TestDiscovererPluginInformation))
Type type = typeof(TPluginInfo);

if (type == typeof(TestDiscovererPluginInformation))
{
this.AreTestDiscoverersCached = true;
}
else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation))
else if (type == typeof(TestExecutorPluginInformation))
{
this.AreTestExecutorsCached = true;
}
else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation2))
else if (type == typeof(TestExecutorPluginInformation2))
{
this.AreTestExecutors2Cached = true;
}
else if (typeof(TPluginInfo) == typeof(TestLoggerPluginInformation))
else if (type == typeof(TestLoggerPluginInformation))
{
this.AreTestLoggersCached = true;
}
else if (typeof(TPluginInfo) == typeof(TestSettingsProviderPluginInformation))
else if (type == typeof(TestSettingsProviderPluginInformation))
{
this.AreTestSettingsProvidersCached = true;
}
else if (typeof(TPluginInfo) == typeof(TestRuntimePluginInformation))
else if (type == typeof(TestRuntimePluginInformation))
{
this.AreTestHostsCached = true;
}
else if (typeof(TPluginInfo) == typeof(DataCollectorConfig))
else if (type == typeof(DataCollectorConfig))
{
this.AreDataCollectorsCached = true;
}
Expand Down Expand Up @@ -358,31 +364,33 @@ internal void InvalidateCache()

private void SetTestExtensionCache<TPluginInfo>(Dictionary<string, TPluginInfo> testPluginInfos) where TPluginInfo : TestPluginInformation
{
if (typeof(TPluginInfo) == typeof(TestDiscovererPluginInformation))
Type type = typeof(TPluginInfo);

if (type == typeof(TestDiscovererPluginInformation))
{
this.TestDiscoverers = (Dictionary<string, TestDiscovererPluginInformation>)(object)testPluginInfos;
}
else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation))
else if (type == typeof(TestExecutorPluginInformation))
{
this.TestExecutors = (Dictionary<string, TestExecutorPluginInformation>)(object)testPluginInfos;
}
else if (typeof(TPluginInfo) == typeof(TestExecutorPluginInformation2))
else if (type == typeof(TestExecutorPluginInformation2))
{
this.TestExecutors2 = (Dictionary<string, TestExecutorPluginInformation2>)(object)testPluginInfos;
}
else if (typeof(TPluginInfo) == typeof(TestLoggerPluginInformation))
else if (type == typeof(TestLoggerPluginInformation))
{
this.TestLoggers = (Dictionary<string, TestLoggerPluginInformation>)(object)testPluginInfos;
}
else if (typeof(TPluginInfo) == typeof(TestSettingsProviderPluginInformation))
else if (type == typeof(TestSettingsProviderPluginInformation))
{
this.TestSettingsProviders = (Dictionary<string, TestSettingsProviderPluginInformation>)(object)testPluginInfos;
}
else if (typeof(TPluginInfo) == typeof(TestRuntimePluginInformation))
else if (type == typeof(TestRuntimePluginInformation))
{
this.TestHosts = (Dictionary<string, TestRuntimePluginInformation>)(object)testPluginInfos;
}
else if (typeof(TPluginInfo) == typeof(DataCollectorConfig))
else if (type == typeof(DataCollectorConfig))
{
this.DataCollectors = (Dictionary<string, DataCollectorConfig>)(object)testPluginInfos;
}
Expand Down
Expand Up @@ -3,6 +3,8 @@

using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.TestPlatform.Extensions.BlameDataCollector;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
Expand All @@ -12,6 +14,7 @@
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyProduct("Microsoft.TestPlatform.Extensions.BlameDataCollector")]
[assembly: AssemblyTrademark("")]
[assembly: TypesToLoad(typeof(BlameLogger), typeof(BlameCollector))]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
Expand Down

0 comments on commit 67689ab

Please sign in to comment.