diff --git a/Container/Data/Constants.cs b/Container/Data/Constants.cs new file mode 100644 index 0000000..312761d --- /dev/null +++ b/Container/Data/Constants.cs @@ -0,0 +1,113 @@ +using System; + +namespace Examples +{ + public abstract partial class PatternBase + { + #region Constants + + public const string Name = "name"; + public const string Null = "null"; + + // TODO: Is it used? + protected const string MethodName = "TestMethod"; + protected const string FieldName = "DependencyField"; + protected const string PropertyName = "DependencyProperty"; + protected const string ParameterName = "dependency"; + + protected const string TDependency = "TDependency"; + + protected const string TEST = "Testing"; + protected const string OVERRIDE = "Override"; + protected const string PARAMETER = "With"; + protected const string CATEGORY_INJECT = "Injecting"; + protected const string MEMBER_OVERRIDE = "MemberOverride"; + protected const string VALIDATION = "Validation"; + protected const string IMPORTING = "Importing"; + protected const string HIERARCHY = "Hierarchy"; + protected const string RESOLVING = "Resolving"; + protected const string ROOT_CONTAINER = "Root Container"; + protected const string CHILD_CONTAINER = "Child Container"; + protected const string REGISTERED = "Registered"; + protected const string UNREGISTERED = "Unregistered"; + protected const string BUILT_IN = "Built-In"; + protected const string GENERIC = "Generic"; + + protected const string As_Annotated = "Resolve as annotated"; + protected const string As_Annotated_Named = "Resolve with annotated name"; + + #endregion + + + #region Members + + protected const string CONSTRUCTORS = "Constructors"; + protected const string METHODS = "Methods"; + protected const string FIELDS = "Fields"; + protected const string PROPERTIES = "Properties"; + + #endregion + + + #region Annotations + + protected const string IMPORT_IMPLICIT = "Implicit"; + protected const string IMPORT_REQUIRED = "Required"; + protected const string IMPORT_OPTIONAL = "Optional"; + + #endregion + + + #region Integer + + public const int NamedInt = 1234; + public const int DefaultInt = 3456; + public const int DefaultValueInt = 4567; + public const int InjectedInt = 6789; + public const int RegisteredInt = 8901; + public const int OverriddenInt = 9012; + + #endregion + + + #region String + + public const string NamedString = "named"; + public const string DefaultString = "default"; + public const string DefaultValueString = "default_value"; + public const string RegisteredString = "registered"; + public const string InjectedString = "injected"; + public const string OverriddenString = "overridden"; + + #endregion + + + #region Unresolvable + + public readonly static Unresolvable NamedUnresolvable = Unresolvable.Create(NamedString); + public readonly static Unresolvable DefaultUnresolvable = Unresolvable.Create(DefaultString); + public readonly static Unresolvable DefaultValueUnresolvable = Unresolvable.Create(DefaultValueString); + public readonly static Unresolvable RegisteredUnresolvable = Unresolvable.Create(RegisteredString); + public readonly static Unresolvable InjectedUnresolvable = SubUnresolvable.Create(InjectedString); + public readonly static Unresolvable OverriddenUnresolvable = SubUnresolvable.Create(OverriddenString); + + #endregion + + + #region Unresolvable Type Instances + + public const bool RegisteredBool = true; + public const long RegisteredLong = 12; + public const short RegisteredShort = 23; + public const float RegisteredFloat = 34; + public const double RegisteredDouble = 45; + public static Type RegisteredType = typeof(PatternBase); + public static ICloneable RegisteredICloneable = new object[0]; + public static Delegate RegisteredDelegate = (Func)(() => 0); + + #endregion + + } +} + + diff --git a/Container/Data/PatternBase.cs b/Container/Data/PatternBase.cs new file mode 100644 index 0000000..c53bf76 --- /dev/null +++ b/Container/Data/PatternBase.cs @@ -0,0 +1,43 @@ +using Unity; + +namespace Examples +{ + public abstract partial class PatternBase + { + #region Fields + + protected IUnityContainer Container; + + #endregion + + + #region Scaffolding + + public virtual void TestInitialize() + { + Container = new UnityContainer(); + + Container.RegisterInstance(RegisteredInt) + .RegisterInstance(Name, NamedInt) + .RegisterInstance(RegisteredString) + .RegisterInstance(Name, NamedString) + .RegisterInstance(RegisteredUnresolvable) + .RegisterInstance(Name, NamedUnresolvable) + .RegisterInstance(typeof(string), Null, (object)null) + .RegisterInstance(typeof(Unresolvable), Null, (object)null) + .RegisterInstance(RegisteredBool) + .RegisterInstance(RegisteredLong) + .RegisterInstance(RegisteredShort) + .RegisterInstance(RegisteredFloat) + .RegisterInstance(RegisteredDouble) + .RegisterInstance(RegisteredType) + .RegisterInstance(RegisteredICloneable) + .RegisterInstance(RegisteredDelegate); + } + + #endregion + + } +} + + diff --git a/Container/Data/Types/Implicit.cs b/Container/Data/Types/Implicit.cs new file mode 100644 index 0000000..598200f --- /dev/null +++ b/Container/Data/Types/Implicit.cs @@ -0,0 +1,19 @@ +namespace Examples.Implicit +{ + #region Baseline + + public class TestType + { + public TestType(TDependency dependency) => DependencyCtor = dependency; + + public void TestMethod(TDependency dependency) => DependencyMethod = dependency; + + + public TDependency DependencyField; + public TDependency DependencyProperty { get; set; } + public TDependency DependencyCtor { get; private set; } + public TDependency DependencyMethod { get; private set; } + } + + #endregion +} diff --git a/Container/Data/Types/Optional.cs b/Container/Data/Types/Optional.cs new file mode 100644 index 0000000..0963cd3 --- /dev/null +++ b/Container/Data/Types/Optional.cs @@ -0,0 +1,85 @@ +using Unity; + + +namespace Examples.Optional +{ + public class TestType + { + #region Constructor + + public TestType([OptionalDependency] TDependency dependency) => DependencyCtor = dependency; + + #endregion + + + #region Method + + public void TestMethod([OptionalDependency] TDependency dependency) => DependencyMethod = dependency; + + #endregion + + + #region Field + + [OptionalDependency] + public TDependency DependencyField; + + #endregion + + + #region Property + + [OptionalDependency] + public TDependency DependencyProperty { get; set; } + + #endregion + + + #region Dependencies + + public TDependency DependencyCtor { get; private set; } + public TDependency DependencyMethod { get; private set; } + + #endregion + } + + public class TestTypeNamed + { + #region Constructor + + public TestTypeNamed([OptionalDependency(PatternBase.Name)] TDependency dependency) => DependencyCtor = dependency; + + #endregion + + + #region Method + + public void TestMethod([OptionalDependency(PatternBase.Name)] TDependency dependency) => DependencyMethod = dependency; + + #endregion + + + #region Field + + [OptionalDependency(PatternBase.Name)] + public TDependency DependencyField; + + #endregion + + + #region Property + + [OptionalDependency(PatternBase.Name)] + public TDependency DependencyProperty { get; set; } + + #endregion + + + #region Dependencies + + public TDependency DependencyCtor { get; private set; } + public TDependency DependencyMethod { get; private set; } + + #endregion + } +} diff --git a/Container/Data/Types/Required.cs b/Container/Data/Types/Required.cs new file mode 100644 index 0000000..e8c81ee --- /dev/null +++ b/Container/Data/Types/Required.cs @@ -0,0 +1,37 @@ +using Unity; + + +namespace Examples.Required +{ + public class TestType + { + public TestType([Dependency] TDependency dependency) => DependencyCtor = dependency; + + public void TestMethod([Dependency] TDependency dependency) => DependencyMethod = dependency; + + [Dependency] + public TDependency DependencyField; + + [Dependency] + public TDependency DependencyProperty { get; set; } + + public TDependency DependencyCtor { get; private set; } + public TDependency DependencyMethod { get; private set; } + } + + public class TestTypeNamed + { + public TestTypeNamed([Dependency(PatternBase.Name)] TDependency dependency) => DependencyCtor = dependency; + + public void TestMethod([Dependency(PatternBase.Name)] TDependency dependency) => DependencyMethod = dependency; + + [Dependency(PatternBase.Name)] + public TDependency DependencyField; + + [Dependency(PatternBase.Name)] + public TDependency DependencyProperty { get; set; } + + public TDependency DependencyCtor { get; private set; } + public TDependency DependencyMethod { get; private set; } + } +} diff --git a/Container/Data/Unresolvable.cs b/Container/Data/Unresolvable.cs new file mode 100644 index 0000000..4476eb9 --- /dev/null +++ b/Container/Data/Unresolvable.cs @@ -0,0 +1,40 @@ +using System; + +namespace Examples +{ + + public interface IUnresolvable { } + + public abstract class PatternBaseType + { + #region Properties + + public virtual object Value { get; protected set; } + public virtual object Default { get; protected set; } + + #endregion + } + + + public class Unresolvable : PatternBaseType, IUnresolvable + { + protected Unresolvable(string id) { Value = id; } + + public static Unresolvable Create(string name) => new Unresolvable(name); + + public override string ToString() => $"Unresolvable.{Value}"; + } + + + public class SubUnresolvable : Unresolvable + { + private SubUnresolvable(string id) + : base(id) { } + + public override string ToString() => $"SubUnresolvable.{Value}"; + + public new static SubUnresolvable Create(string name) => new SubUnresolvable(name); + } +} + + diff --git a/Container/Injecting/Constructors/ResolvedParameter.cs b/Container/Injecting/Constructors/ResolvedParameter.cs new file mode 100644 index 0000000..af39e98 --- /dev/null +++ b/Container/Injecting/Constructors/ResolvedParameter.cs @@ -0,0 +1,44 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Unity.Injection; +using Unity; + +namespace Injecting +{ + public partial class Constructors + { + #region ResolvedParameter() + + [TestMethod(As_Annotated), TestProperty(PARAMETER, nameof(ResolvedParameter))] + public void With_ResolvedParameter() + { + // Inject parameter with value resolved from container with contract + // determined by ParameterInfo + Container.RegisterType>( + new InjectionConstructor(new ResolvedParameter())); + + // Resolve with non attributed dependency + var instance = Container.Resolve>(); + + // By default resolved unnamed contract + Assert.AreEqual(RegisteredString, instance.DependencyCtor); + } + + + [TestMethod(As_Annotated_Named), TestProperty(PARAMETER, nameof(ResolvedParameter))] + public void Named_With_ResolvedParameter() + { + // Inject parameter with value resolved from container with contract + // determined by ParameterInfo + Container.RegisterType>( + new InjectionConstructor(new ResolvedParameter())); + + // Resolve Required, Named dependency + var instance = Container.Resolve>(); + + // Verify resolved named contract + Assert.AreEqual(NamedString, instance.DependencyCtor); + } + + #endregion + } +} diff --git a/Container/Injecting/Constructors/Setup.cs b/Container/Injecting/Constructors/Setup.cs new file mode 100644 index 0000000..37897be --- /dev/null +++ b/Container/Injecting/Constructors/Setup.cs @@ -0,0 +1,12 @@ +using Examples; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Injecting +{ + [TestClass] + public partial class Constructors : PatternBase + { + [TestInitialize] + public override void TestInitialize() => base.TestInitialize(); + } +} diff --git a/Container/Injecting/Fields/ResolvedParameter.cs b/Container/Injecting/Fields/ResolvedParameter.cs new file mode 100644 index 0000000..9583df6 --- /dev/null +++ b/Container/Injecting/Fields/ResolvedParameter.cs @@ -0,0 +1,44 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Unity.Injection; +using Unity; + +namespace Injecting +{ + public partial class Fields + { + #region ResolvedParameter() + + [TestMethod(As_Annotated), TestProperty(PARAMETER, nameof(ResolvedParameter))] + public void With_ResolvedParameter() + { + // Inject field with value resolved from container with contract + // determined by FieldInfo + Container.RegisterType>( + new InjectionField(FieldName, new ResolvedParameter())); + + // Resolve with non attributed dependency + var instance = Container.Resolve>(); + + // By default resolved unnamed contract + Assert.AreEqual(RegisteredString, instance.DependencyField); + } + + + [TestMethod(As_Annotated_Named), TestProperty(PARAMETER, nameof(ResolvedParameter))] + public void Named_With_ResolvedParameter() + { + // Inject field with value resolved from container with contract + // determined by FieldInfo + Container.RegisterType>( + new InjectionField(FieldName, new ResolvedParameter())); + + // Resolve Required, Named dependency + var instance = Container.Resolve>(); + + // Verify resolved named contract + Assert.AreEqual(NamedString, instance.DependencyField); + } + + #endregion + } +} diff --git a/Container/Injecting/Fields/Setup.cs b/Container/Injecting/Fields/Setup.cs new file mode 100644 index 0000000..90ec5cd --- /dev/null +++ b/Container/Injecting/Fields/Setup.cs @@ -0,0 +1,12 @@ +using Examples; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Injecting +{ + [TestClass] + public partial class Fields : PatternBase + { + [TestInitialize] + public override void TestInitialize() => base.TestInitialize(); + } +} diff --git a/Container/Injecting/Methods/ResolvedParameter.cs b/Container/Injecting/Methods/ResolvedParameter.cs new file mode 100644 index 0000000..e455f44 --- /dev/null +++ b/Container/Injecting/Methods/ResolvedParameter.cs @@ -0,0 +1,44 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Unity.Injection; +using Unity; + +namespace Injecting +{ + public partial class Methods + { + #region ResolvedParameter() + + [TestMethod(As_Annotated), TestProperty(PARAMETER, nameof(ResolvedParameter))] + public void With_ResolvedParameter() + { + // Inject parameter with value resolved from container with contract + // determined by ParameterInfo + Container.RegisterType>( + new InjectionMethod(MethodName, new ResolvedParameter())); + + // Resolve with non attributed dependency + var instance = Container.Resolve>(); + + // By default resolved unnamed contract + Assert.AreEqual(RegisteredString, instance.DependencyMethod); + } + + + [TestMethod(As_Annotated_Named), TestProperty(PARAMETER, nameof(ResolvedParameter))] + public void Named_With_ResolvedParameter() + { + // Inject parameter with value resolved from container with contract + // determined by ParameterInfo + Container.RegisterType>( + new InjectionMethod(MethodName, new ResolvedParameter())); + + // Resolve Required, Named dependency + var instance = Container.Resolve>(); + + // Verify resolved named contract + Assert.AreEqual(NamedString, instance.DependencyMethod); + } + + #endregion + } +} diff --git a/Container/Injecting/Methods/Setup.cs b/Container/Injecting/Methods/Setup.cs new file mode 100644 index 0000000..61d8f1b --- /dev/null +++ b/Container/Injecting/Methods/Setup.cs @@ -0,0 +1,12 @@ +using Examples; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Injecting +{ + [TestClass] + public partial class Methods : PatternBase + { + [TestInitialize] + public override void TestInitialize() => base.TestInitialize(); + } +} diff --git a/Container/Injecting/Properties/ResolvedParameter.cs b/Container/Injecting/Properties/ResolvedParameter.cs new file mode 100644 index 0000000..e9bbec2 --- /dev/null +++ b/Container/Injecting/Properties/ResolvedParameter.cs @@ -0,0 +1,44 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Unity.Injection; +using Unity; + +namespace Injecting +{ + public partial class Properties + { + #region ResolvedParameter() + + [TestMethod(As_Annotated), TestProperty(PARAMETER, nameof(ResolvedParameter))] + public void With_ResolvedParameter() + { + // Inject property with value resolved from container with contract + // determined by PropertyInfo + Container.RegisterType>( + new InjectionProperty(PropertyName, new ResolvedParameter())); + + // Resolve with non attributed dependency + var instance = Container.Resolve>(); + + // By default resolved unnamed contract + Assert.AreEqual(RegisteredString, instance.DependencyProperty); + } + + + [TestMethod(As_Annotated_Named), TestProperty(PARAMETER, nameof(ResolvedParameter))] + public void Named_With_ResolvedParameter() + { + // Inject property with value resolved from container with contract + // determined by PropertyInfo + Container.RegisterType>( + new InjectionProperty(PropertyName, new ResolvedParameter())); + + // Resolve Required, Named dependency + var instance = Container.Resolve>(); + + // Verify resolved named contract + Assert.AreEqual(NamedString, instance.DependencyProperty); + } + + #endregion + } +} diff --git a/Container/Injecting/Properties/Setup.cs b/Container/Injecting/Properties/Setup.cs new file mode 100644 index 0000000..c5f2d7b --- /dev/null +++ b/Container/Injecting/Properties/Setup.cs @@ -0,0 +1,12 @@ +using Examples; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Injecting +{ + [TestClass] + public partial class Properties : PatternBase + { + [TestInitialize] + public override void TestInitialize() => base.TestInitialize(); + } +} diff --git a/Container/README.md b/Container/README.md new file mode 100644 index 0000000..c6f1d64 --- /dev/null +++ b/Container/README.md @@ -0,0 +1,17 @@ +# Container Regression Tests + +This project contains regression tests for the Unity Container. +The tests are run against various versions of the container and demonstrate differences in the behavior. + +## Running Tests + +To run tests just clone this branch into your hard disk and open project file + +## Version Info + +By default the solution compares container behavior from 4 different releases: + +* [Unity v4.0.1](https://github.com/unitycontainer/unity/tree/release/4.0.x) (.NET 4.6.x) +* [Unity v5.11](https://github.com/unitycontainer/unity/releases/tag/5.11.6.966) (.NET 4.7.x) +* [Unity v5.12 - beta](https://github.com/unitycontainer/container/tree/release/5.12.0) (.NET 4.8) +* [Unity v6.0 - alpha](https://github.com/unitycontainer/container/tree/release/6.0.0) (.NET 5.0) diff --git a/Container/Unity.Container.Examples.csproj b/Container/Unity.Container.Examples.csproj new file mode 100644 index 0000000..33630ea --- /dev/null +++ b/Container/Unity.Container.Examples.csproj @@ -0,0 +1,22 @@ + + + + net472 + latest + false + false + + + + + + + + + + + + + + + \ No newline at end of file