diff --git a/build.cake b/build.cake index 2626ea3..2afc826 100644 --- a/build.cake +++ b/build.cake @@ -19,8 +19,6 @@ BuildSettings.Packages.Add(new NuGetPackage( source: "nuget/TestCentric.Extensibility.nuspec", checks: new PackageCheck[] { HasFiles("LICENSE.txt", "README.md", "testcentric.png"), - //HasDirectory("lib/net20") - // .WithFiles("TestCentric.Extensibility.dll", "TestCentric.Extensibility.api.dll", "nunit.engine.api.dll"), HasDirectory("lib/net462") .WithFiles("testcentric.extensibility.dll", "TestCentric.Extensibility.api.dll", "nunit.engine.api.dll"), HasDirectory("lib/netstandard2.0") @@ -49,7 +47,6 @@ BuildSettings.Packages.Add(new NuGetPackage( checks: new PackageCheck[] { HasFiles( "LICENSE.txt", "README.md", "testcentric.png", - "lib/net20/testcentric.extensibility.api.dll", "lib/net462/testcentric.extensibility.api.dll", "lib/netstandard2.0/testcentric.extensibility.api.dll") })); diff --git a/nuget/TestCentric.Extensibility.Api.nuspec b/nuget/TestCentric.Extensibility.Api.nuspec index 9f4372c..4b19d06 100644 --- a/nuget/TestCentric.Extensibility.Api.nuspec +++ b/nuget/TestCentric.Extensibility.Api.nuspec @@ -18,7 +18,6 @@ - diff --git a/nuget/TestCentric.Extensibility.nuspec b/nuget/TestCentric.Extensibility.nuspec index 9121333..e29fab8 100644 --- a/nuget/TestCentric.Extensibility.nuspec +++ b/nuget/TestCentric.Extensibility.nuspec @@ -22,11 +22,6 @@ - diff --git a/src/testcentric.extensibility.api/testcentric.extensibility.api.csproj b/src/testcentric.extensibility.api/testcentric.extensibility.api.csproj index 823c918..477f8d4 100644 --- a/src/testcentric.extensibility.api/testcentric.extensibility.api.csproj +++ b/src/testcentric.extensibility.api/testcentric.extensibility.api.csproj @@ -1,7 +1,7 @@  - net20;net462;netstandard2.0 + net462;netstandard2.0 TestCentric.Extensibility enable diff --git a/src/testcentric.extensibility.fakes/FakeExtensions.cs b/src/testcentric.extensibility.fakes/FakeExtensions.cs index e1a9103..ecc4053 100644 --- a/src/testcentric.extensibility.fakes/FakeExtensions.cs +++ b/src/testcentric.extensibility.fakes/FakeExtensions.cs @@ -123,4 +123,13 @@ public void OnTestEvent(string text) throw new System.NotImplementedException(); } } + + [NUnit.Extensibility.Extension] + public class FakeNUnit4Listener : NUnit.Engine.ITestEventListener + { + public void OnTestEvent(string text) + { + throw new System.NotImplementedException(); + } + } } diff --git a/src/testcentric.extensibility.fakes/TestCentric.Extensibility.FakeExtensions.csproj b/src/testcentric.extensibility.fakes/TestCentric.Extensibility.FakeExtensions.csproj index a21ad86..101671e 100644 --- a/src/testcentric.extensibility.fakes/TestCentric.Extensibility.FakeExtensions.csproj +++ b/src/testcentric.extensibility.fakes/TestCentric.Extensibility.FakeExtensions.csproj @@ -1,7 +1,7 @@  - net20;net462;netstandard2.0 + net462;netstandard2.0 TestCentric.Extensibility true testcentric.snk diff --git a/src/testcentric.extensibility.tests/ExtensionAssemblyTests.cs b/src/testcentric.extensibility.tests/ExtensionAssemblyTests.cs index f5d23b9..8895350 100644 --- a/src/testcentric.extensibility.tests/ExtensionAssemblyTests.cs +++ b/src/testcentric.extensibility.tests/ExtensionAssemblyTests.cs @@ -55,11 +55,7 @@ public void TargetFramework() { var framework = _ea.FrameworkName; Assert.That(_ea.FrameworkName.Identifier, Is.EqualTo(".NETFramework")); -#if NET20 || NET35 - Assert.That(_ea.FrameworkName.Version, Is.EqualTo(new Version(2, 0))); -#else Assert.That(_ea.FrameworkName.Version, Is.EqualTo(new Version(4, 6, 2))); -#endif } #endif } diff --git a/src/testcentric.extensibility.tests/ExtensionManagerTests.cs b/src/testcentric.extensibility.tests/ExtensionManagerTests.cs index ea83d13..ec3b441 100644 --- a/src/testcentric.extensibility.tests/ExtensionManagerTests.cs +++ b/src/testcentric.extensibility.tests/ExtensionManagerTests.cs @@ -122,39 +122,54 @@ internal class ThisIsNotAnExtensionPoint "TestCentric.Engine.Extensibility.FakeTestEventListener", "TestCentric.Engine.Extensibility.FakeProjectLoader", "TestCentric.Engine.Extensibility.FakeResultWriter", - "TestCentric.Engine.Extensibility.FakeNUnitExtension_ThrowsInConstructor" + "TestCentric.Engine.Extensibility.FakeNUnitExtension_ThrowsInConstructor", + "TestCentric.Engine.Extensibility.FakeNUnit4Listener" ]; - [Test] + private static string[] KnownExtensionPaths = + [ + "/TestCentric/Engine/AgentLaunchers", + "/TestCentric/Engine/AgentLaunchers", + "/TestCentric/Engine/TestEventListeners", + "/TestCentric/Engine/ProjectLoaders", + "/TestCentric/Engine/ResultWriters", + "/TestCentric/Engine/TestEventListeners", + "/TestCentric/Engine/TestEventListeners" + ]; + + private const string INITIALLY_DISABLED_EXTENSION = "TestCentric.Engine.Extensibility.FakeTestEventListener"; + [Test, Order(1)] public void AllExtensionsAreKnown() { Assert.That(ExtensionManager.Extensions.Select(ep => ep.TypeName), Is.EquivalentTo(KnownExtensionTypeNames)); } - // Run this first as subsequent test will enable the extension - [Test, Order(1)] - public void ExtensionMayBeDisabledByDefault() + [TestCaseSource(nameof(KnownExtensionTypeNames)), Order(2)] + public void ExtensionStatusIsCorrect(string typeName) { - Assert.That(ExtensionManager.Extensions, - Has.One.Property(nameof(ExtensionNode.TypeName)).EqualTo("TestCentric.Engine.Extensibility.FakeTestEventListener") - .And.Property(nameof(ExtensionNode.Enabled)).False); + Assert.That(GetExtensionNode(typeName).Status, Is.EqualTo(ExtensionStatus.Unloaded)); } - [Test] - public void DisabledExtensionMayBeEnabled() + [Test, Sequential, Order(3)] + public void ExtensionsAreEnabledAsExpected( + [ValueSource(nameof(KnownExtensionTypeNames))] string typeName, + [Values(true, false, false, true, true, false, true)] bool enabled) { - ExtensionManager.EnableExtension("TestCentric.Engine.Extensibility.FakeTestEventListener", true); + Assert.That(GetExtensionNode(typeName).Enabled, Is.EqualTo(enabled)); + } - Assert.That(ExtensionManager.Extensions, - Has.One.Property(nameof(ExtensionNode.TypeName)).EqualTo("TestCentric.Engine.Extensibility.FakeTestEventListener") - .And.Property(nameof(ExtensionNode.Enabled)).True); + [Test, Order(4)] + public void ExtensionMayBeDisabledByDefault() + { + Assert.That(GetExtensionNode(INITIALLY_DISABLED_EXTENSION).Enabled, Is.False); + ExtensionManager.EnableExtension(INITIALLY_DISABLED_EXTENSION, true); + Assert.That(GetExtensionNode(INITIALLY_DISABLED_EXTENSION).Enabled, Is.True); } [Test] public void NUnitExtensionThrowsInConstructor() { - string typeName = "TestCentric.Engine.Extensibility.FakeNUnitExtension_ThrowsInConstructor"; - var exNode = ExtensionManager.Extensions.Where(n => n.TypeName == typeName).Single(); + var exNode = GetExtensionNode("TestCentric.Engine.Extensibility.FakeNUnitExtension_ThrowsInConstructor"); // Although the constructor throws, we don't get an exception. // However, the node contains the error information. @@ -178,25 +193,19 @@ public void TestCentricExtensionThrowsInConstructor() Assert.That(exNode.Exception.InnerException, Is.InstanceOf()); } -#if NETCOREAPP - [TestCase("netstandard2.0", ExpectedResult = true)] - [TestCase("net462", ExpectedResult = false)] - [TestCase("net20", ExpectedResult = false)] -#elif NET40_OR_GREATER +#if NETFRAMEWORK [TestCase("netstandard2.0", ExpectedResult = false)] [TestCase("net462", ExpectedResult = true)] - [TestCase("net20", ExpectedResult = true)] #else - [TestCase("netstandard2.0", ExpectedResult = false)] + [TestCase("netstandard2.0", ExpectedResult = true)] [TestCase("net462", ExpectedResult = false)] - [TestCase("net20", ExpectedResult = true)] #endif public bool LoadTargetFramework(string tfm) { return ExtensionManager.CanLoadTargetFramework(THIS_ASSEMBLY, FakeExtensions(tfm)); } - #endregion +#endregion private const string FAKE_EXTENSIONS_FILENAME = "TestCentric.Extensibility.FakeExtensions.dll"; private static readonly string FAKE_EXTENSIONS_PARENT_DIRECTORY = @@ -213,5 +222,8 @@ private static ExtensionAssembly FakeExtensions(string tfm) return new ExtensionAssembly( Path.Combine(FAKE_EXTENSIONS_PARENT_DIRECTORY, Path.Combine(tfm, FAKE_EXTENSIONS_FILENAME)), false); } + + private ExtensionNode GetExtensionNode(string typeName) => + ExtensionManager.Extensions.Where(n => n.TypeName == typeName).Single(); } } diff --git a/src/testcentric.extensibility.tests/testcentric.extensibility.tests.csproj b/src/testcentric.extensibility.tests/testcentric.extensibility.tests.csproj index 25b8f2f..603fe91 100644 --- a/src/testcentric.extensibility.tests/testcentric.extensibility.tests.csproj +++ b/src/testcentric.extensibility.tests/testcentric.extensibility.tests.csproj @@ -1,7 +1,7 @@  - net35;net462;net6.0 + net462;net6.0 TestCentric.Extensibility true testcentric.snk @@ -16,10 +16,6 @@ - - - - diff --git a/src/testcentric.extensibility/Compatibility/System.Runtime.CompilerServices/ExtensionAttribute.cs b/src/testcentric.extensibility/Compatibility/System.Runtime.CompilerServices/ExtensionAttribute.cs deleted file mode 100644 index 79e2795..0000000 --- a/src/testcentric.extensibility/Compatibility/System.Runtime.CompilerServices/ExtensionAttribute.cs +++ /dev/null @@ -1,18 +0,0 @@ -// *********************************************************************** -// Copyright (c) Charlie Poole and TestCentric contributors. -// Licensed under the MIT License. See LICENSE file in root directory. -// *********************************************************************** - -#if NET20 -using System; -using System.Collections.Generic; -using System.Text; - -namespace System.Runtime.CompilerServices -{ - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] - internal sealed class ExtensionAttribute : Attribute - { - } -} -#endif diff --git a/src/testcentric.extensibility/Compatibility/System.Runtime.Versioning/FrameworkName.cs b/src/testcentric.extensibility/Compatibility/System.Runtime.Versioning/FrameworkName.cs deleted file mode 100644 index 326a349..0000000 --- a/src/testcentric.extensibility/Compatibility/System.Runtime.Versioning/FrameworkName.cs +++ /dev/null @@ -1,185 +0,0 @@ -// *********************************************************************** -// Copyright (c) Charlie Poole and TestCentric contributors. -// Licensed under the MIT License. See LICENSE file in root directory. -// *********************************************************************** - -#if NET20 || NET35 -using System.Diagnostics; -using TestCentric.Extensibility; - -namespace System.Runtime.Versioning -{ - /// - /// Compatible implementation of FrameworkName, based on the corefx implementation - /// - internal sealed class FrameworkName : IEquatable - { - private const string FRAMEWORK_NAME_INVALID = "Invalid FrameworkName"; - private const string FRAMEWORK_NAME_VERSION_REQUIRED = "FramweworkName must include Version"; - private const string FRAMEWORK_NAME_VERSION_INVALID = "The specified Version is invalid"; - private const string FRAMEWORK_NAME_COMPONENT_COUNT = "FrameworkName must specify either two or three components"; - - public string Identifier { get; } - - public Version Version { get; } - - public string Profile { get; } - - public string FullName { get; } - //{ - // get - // { - // if (_fullName == null) - // { - -// } - -// Debug.Assert(_fullName != null); -// return _fullName; -// } -//} - - public override bool Equals(object obj) - { - return Equals(obj as FrameworkName); - } - - public bool Equals(FrameworkName? other) - { - if (other is null) - return false; - - return Identifier == other.Identifier && - Version == other.Version && - Profile == other.Profile; - } - - public override int GetHashCode() - { - return Identifier.GetHashCode() ^ Version.GetHashCode() ^ Profile.GetHashCode(); - } - - public override string ToString() - { - return FullName; - } - - public FrameworkName(string identifier, Version version) - : this(identifier, version, null) - { - } - - public FrameworkName(string identifier, Version version, string? profile = null) - { - Guard.ArgumentNotNull(identifier, nameof(identifier)); - Guard.ArgumentNotNull(version, nameof(version)); - - identifier = identifier.Trim(); - Guard.ArgumentNotNullOrEmpty(identifier, nameof(identifier)); - - Identifier = identifier; - Version = version; - Profile = (profile == null) ? string.Empty : profile.Trim(); - FullName = $"{Identifier},Version=v{Version.ToString()}"; - if (!string.IsNullOrEmpty(Profile)) - FullName += $",Profile={Profile}"; - } - - // Parses strings in the following format: ", Version=[v|V], Profile=" - // - The identifier and version is required, profile is optional - // - Only three components are allowed. - // - The version string must be in the System.Version format; an optional "v" or "V" prefix is allowed - public FrameworkName(string frameworkName) - { - Guard.ArgumentNotNullOrEmpty(frameworkName, nameof(frameworkName)); - - string[] components = frameworkName.Split([',']); - - // Identifier and Version are required, Profile is optional. - if (components.Length < 2 || components.Length > 3) - throw new ArgumentException(FRAMEWORK_NAME_COMPONENT_COUNT, nameof(frameworkName)); - - // - // 1) Parse the "Identifier", which must come first. Trim any whitespace - // - Identifier = components[0].Trim(); - if (string.IsNullOrEmpty(Identifier)) - throw new ArgumentException(FRAMEWORK_NAME_INVALID, nameof(frameworkName)); - - Profile = string.Empty; - - // - // The required "Version" and optional "Profile" component can be in any order - // - for (int i = 1; i < components.Length; i++) - { - // Get the key/value pair separated by '=' - string component = components[i]; - int separatorIndex = component.IndexOf('='); - - Guard.ArgumentValid(separatorIndex >= 0 && separatorIndex == component.LastIndexOf('='), - FRAMEWORK_NAME_INVALID, nameof(frameworkName)); - - // Get the key and value, trimming any whitespace - string key = component.Substring(0, separatorIndex).Trim(); - string value = component.Substring(separatorIndex + 1).Trim(); - - // - // 2) Parse the required "Version" key value - // - if (key.Equals("Version", StringComparison.OrdinalIgnoreCase)) - { - // Allow the version to include a 'v' or 'V' prefix... - if (value.Length > 0 && (value[0] == 'v' || value[0] == 'V')) - value = value.Substring(1); - - try - { - Version = new Version(value); - } - catch (Exception e) - { - throw new ArgumentException(FRAMEWORK_NAME_VERSION_INVALID, nameof(frameworkName), e); - } - } - // - // 3) Parse the optional "Profile" key value - // - else if (key.Equals("Profile", StringComparison.OrdinalIgnoreCase)) - { - if (value.Length > 0) - { - Profile = value.ToString(); - } - } - else - { - throw new ArgumentException(FRAMEWORK_NAME_INVALID, nameof(frameworkName)); - } - } - - if (Version is null) - throw new ArgumentException(FRAMEWORK_NAME_VERSION_REQUIRED, nameof(frameworkName)); - - FullName = $"{Identifier},Version=v{Version.ToString()}"; - if (!string.IsNullOrEmpty(Profile)) - FullName += $",Profile={Profile}"; - } - - public static bool operator ==(FrameworkName left, FrameworkName right) - { - if (left is null) - { - return right is null; - } - - return left.Equals(right); - } - - public static bool operator !=(FrameworkName left, FrameworkName right) - { - return !(left == right); - } - } -} -#endif diff --git a/src/testcentric.extensibility/ExtensionAssemblyTracker.cs b/src/testcentric.extensibility/ExtensionAssemblyTracker.cs index 1744465..6927938 100644 --- a/src/testcentric.extensibility/ExtensionAssemblyTracker.cs +++ b/src/testcentric.extensibility/ExtensionAssemblyTracker.cs @@ -17,13 +17,8 @@ internal class ExtensionAssemblyTracker : IEnumerable { private static readonly Logger log = InternalTrace.GetLogger(typeof(ExtensionAssemblyTracker)); -#if NET20 - private readonly Dictionary _evaluatedPaths = new Dictionary(); - public bool ContainsPath(string path) => _evaluatedPaths.ContainsKey(path); -#else private readonly HashSet _evaluatedPaths = new HashSet(); public bool ContainsPath(string path) => _evaluatedPaths.Contains(path); -#endif private readonly Dictionary _byName = new Dictionary(); @@ -36,11 +31,8 @@ internal class ExtensionAssemblyTracker : IEnumerable public void AddOrUpdate(ExtensionAssembly candidateAssembly) { string assemblyName = candidateAssembly.AssemblyName; -#if NET20 - _evaluatedPaths.Add(candidateAssembly.FilePath, true); -#else _evaluatedPaths.Add(candidateAssembly.FilePath); -#endif + // Do we already have a copy of the same assembly at a different path? if (_byName.TryGetValue(assemblyName, out var existing)) { diff --git a/src/testcentric.extensibility/ExtensionManager.cs b/src/testcentric.extensibility/ExtensionManager.cs index 89128d0..231392c 100644 --- a/src/testcentric.extensibility/ExtensionManager.cs +++ b/src/testcentric.extensibility/ExtensionManager.cs @@ -9,11 +9,7 @@ using System.Reflection; using TestCentric.Metadata; -#if NET20 -using NUNIT = NUnit.Engine.Extensibility; -#else using NUNIT = NUnit.Extensibility; -#endif namespace TestCentric.Extensibility { diff --git a/src/testcentric.extensibility/ExtensionNode.cs b/src/testcentric.extensibility/ExtensionNode.cs index 9e33136..027fa0c 100644 --- a/src/testcentric.extensibility/ExtensionNode.cs +++ b/src/testcentric.extensibility/ExtensionNode.cs @@ -5,9 +5,7 @@ using System; using System.Collections.Generic; -#if !NET20 using System.Linq; -#endif using System.Reflection; namespace TestCentric.Extensibility @@ -103,11 +101,7 @@ public IEnumerable GetValues(string name) if (_properties.TryGetValue(name, out List? value)) return value; else -#if NET20 - return new string[0]; -#else return Enumerable.Empty(); -#endif } /// diff --git a/src/testcentric.extensibility/testcentric.extensibility.csproj b/src/testcentric.extensibility/testcentric.extensibility.csproj index 89ce786..962cac9 100644 --- a/src/testcentric.extensibility/testcentric.extensibility.csproj +++ b/src/testcentric.extensibility/testcentric.extensibility.csproj @@ -1,7 +1,7 @@  - net20;net462;netstandard2.0 + net462;netstandard2.0 TestCentric.Extensibility 618 enable