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 authored Nov 19, 2020
1 parent 2a3fd2c commit 67689ab
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 71 deletions.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ public Dictionary<string, TPluginInfo> DiscoverTestExtensions<TPluginInfo, TExte
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
Original file line number Diff line number Diff line change
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 GetTestExtensionsFromAssembly<TPluginInfo, TExtension>(Assembly ass
{
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 GetTestExtensionsFromAssembly<TPluginInfo, TExtension>(Assembly ass
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 GetTestExtensionFromType<TPluginInfo>(
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 Dictionary<string, TPluginInfo> GetTestExtensionCache<TPluginInfo>() wh
/// </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 bool AreTestExtensionsCached<TPluginInfo>() where TPluginInfo : TestPlu
/// </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 Dictionary<string, TPluginInfo> GetExtensionsDiscoveredFromAssembly<TPl

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
Original file line number Diff line number Diff line change
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
Loading

0 comments on commit 67689ab

Please sign in to comment.