/// <summary> /// Construct an ExtensionNode supplying the assembly path and type name. /// </summary> /// <param name="assemblyPath">The path to the assembly where this extension is found.</param> /// <param name="typeName">The full name of the Type of the extension object.</param> /// <param name="targetFramework">The target framework of the extension assembly.</param> public ExtensionNode(string assemblyPath, string typeName, IRuntimeFramework targetFramework) { AssemblyPath = assemblyPath; TypeName = typeName; TargetFramework = targetFramework; Enabled = true; // By default }
/// <summary> /// Scan a single assembly for extensions marked by ExtensionAttribute. /// For each extension, create an ExtensionNode and link it to the /// correct ExtensionPoint. Public for testing. /// </summary> internal void FindExtensionsInAssembly(ExtensionAssembly assembly) { log.Info("Scanning {0} assembly for Extensions", assembly.FilePath); if (CanLoadTargetFramework(Assembly.GetEntryAssembly(), assembly)) { IRuntimeFramework assemblyTargetFramework = null; #if !NETSTANDARD2_0 var currentFramework = RuntimeFramework.CurrentFramework; assemblyTargetFramework = assembly.TargetFramework; if (!currentFramework.CanLoad(assemblyTargetFramework)) { if (!assembly.FromWildCard) { throw new NUnitEngineException($"Extension {assembly.FilePath} targets {assemblyTargetFramework.DisplayName}, which is not available."); } else { log.Info($"Assembly {assembly.FilePath} targets {assemblyTargetFramework.DisplayName}, which is not available. Assembly found via wildcard."); return; } } #endif foreach (var type in assembly.MainModule.GetTypes()) { CustomAttribute extensionAttr = type.GetAttribute("NUnit.Engine.Extensibility.ExtensionAttribute"); if (extensionAttr == null) { continue; } object versionArg = extensionAttr.GetNamedArgument("EngineVersion"); if (versionArg != null && new Version((string)versionArg) > ENGINE_VERSION) { continue; } var node = new ExtensionNode(assembly.FilePath, type.FullName, assemblyTargetFramework); node.Path = extensionAttr.GetNamedArgument("Path") as string; node.Description = extensionAttr.GetNamedArgument("Description") as string; object enabledArg = extensionAttr.GetNamedArgument("Enabled"); node.Enabled = enabledArg != null ? (bool)enabledArg : true; log.Info(" Found ExtensionAttribute on Type " + type.Name); foreach (var attr in type.GetAttributes("NUnit.Engine.Extensibility.ExtensionPropertyAttribute")) { string name = attr.ConstructorArguments[0].Value as string; string value = attr.ConstructorArguments[1].Value as string; if (name != null && value != null) { node.AddProperty(name, value); log.Info(" ExtensionProperty {0} = {1}", name, value); } } _extensions.Add(node); ExtensionPoint ep; if (node.Path == null) { ep = DeduceExtensionPointFromType(type); if (ep == null) { string msg = string.Format( "Unable to deduce ExtensionPoint for Type {0}. Specify Path on ExtensionAttribute to resolve.", type.FullName); throw new NUnitEngineException(msg); } node.Path = ep.Path; } else { ep = GetExtensionPoint(node.Path); if (ep == null) { string msg = string.Format( "Unable to locate ExtensionPoint for Type {0}. The Path {1} cannot be found.", type.FullName, node.Path); throw new NUnitEngineException(msg); } } ep.Install(node); } } }
// Some early versions of the engine return .NET 4.5 Client profile, which doesn't really exist private static bool IsErroneousNet45ClientProfile(IRuntimeFramework runtime) { return(runtime.FrameworkVersion.Major == 4 && runtime.FrameworkVersion.Minor > 0 && runtime.Profile == "Client"); }
/// <summary> /// Scan a single assembly for extensions marked by ExtensionAttribute. /// For each extension, create an ExtensionNode and link it to the /// correct ExtensionPoint. Public for testing. /// </summary> internal void FindExtensionsInAssembly(ExtensionAssembly assembly) { log.Info($"Scanning {assembly.FilePath} for Extensions"); if (!CanLoadTargetFramework(Assembly.GetEntryAssembly(), assembly)) { log.Info($"{assembly.FilePath} cannot be loaded on this runtime"); return; } IRuntimeFramework assemblyTargetFramework = null; #if NETFRAMEWORK var currentFramework = RuntimeFramework.CurrentFramework; assemblyTargetFramework = assembly.TargetFramework; if (!currentFramework.CanLoad(assemblyTargetFramework)) { //Temp fix: Prevent crash in agent if an extension is used by the main engine, which targets a framework that can not be loaded on a particular agent // https://github.com/nunit/nunit-console/issues/757 //Long-term fix is to not search for extensions within the agent, see https://github.com/nunit/nunit-console/issues/760 if (_isRunningOnAgent) { return; } if (!assembly.FromWildCard) { throw new NUnitEngineException($"Extension {assembly.FilePath} targets {assemblyTargetFramework.DisplayName}, which is not available."); } else { log.Info($"Assembly {assembly.FilePath} targets {assemblyTargetFramework.DisplayName}, which is not available. Assembly found via wildcard."); return; } } #endif foreach (var type in assembly.MainModule.GetTypes()) { CustomAttribute extensionAttr = type.GetAttribute("NUnit.Engine.Extensibility.ExtensionAttribute"); if (extensionAttr == null) { continue; } object versionArg = extensionAttr.GetNamedArgument("EngineVersion"); if (versionArg != null && new Version((string)versionArg) > ENGINE_VERSION) { continue; } var node = new ExtensionNode(assembly.FilePath, assembly.AssemblyVersion, type.FullName, assemblyTargetFramework); node.Path = extensionAttr.GetNamedArgument("Path") as string; node.Description = extensionAttr.GetNamedArgument("Description") as string; object enabledArg = extensionAttr.GetNamedArgument("Enabled"); node.Enabled = enabledArg != null ? (bool)enabledArg : true; log.Info(" Found ExtensionAttribute on Type " + type.Name); foreach (var attr in type.GetAttributes("NUnit.Engine.Extensibility.ExtensionPropertyAttribute")) { string name = attr.ConstructorArguments[0].Value as string; string value = attr.ConstructorArguments[1].Value as string; if (name != null && value != null) { node.AddProperty(name, value); log.Info(" ExtensionProperty {0} = {1}", name, value); } } _extensions.Add(node); ExtensionPoint ep; if (node.Path == null) { ep = DeduceExtensionPointFromType(type); if (ep == null) { string msg = string.Format( "Unable to deduce ExtensionPoint for Type {0}. Specify Path on ExtensionAttribute to resolve.", type.FullName); throw new NUnitEngineException(msg); } node.Path = ep.Path; } else { ep = GetExtensionPoint(node.Path); if (ep == null) { string msg = string.Format( "Unable to locate ExtensionPoint for Type {0}. The Path {1} cannot be found.", type.FullName, node.Path); throw new NUnitEngineException(msg); } } ep.Install(node); } }
public bool CanLoad(IRuntimeFramework requested) { return(FrameworkVersion >= requested.FrameworkVersion); }