using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Utility; using Chernobyl.Dependency; using Chernobyl.Reflection; using Chernobyl.Values; using NUnit.Framework; namespace Chernobyl.Attribution { [TestFixture, Description("Tests for the RunAttribute type.")] public class RunAttributeTests { /////////////////////////////////////////////////////////////////////// #region Exception Tests /////////////////////////////////////////////////////////////////////// [Test, Description("MethodException thrown if non-static method is attributed.")] public virtual void MethodExceptionWhenNonStaticMethodAttributed() { Assert.Throws(() => ProcessMethod(Methods.AttributedNonStaticName)); } #endregion /////////////////////////////////////////////////////////////////////// #region IgnoreReturnValue Tests /////////////////////////////////////////////////////////////////////// [Test, Description("MethodException when method has return value and " + "IgnoreReturnValue is false.")] public virtual void MethodExceptionWithReturnValueAndFalseIgnoreReturnValue() { Assert.Throws(() => ProcessMethod(Methods.FalseIgnoreReturnValueName)); } [Test, Description("No MethodException when method has return value and " + "IgnoreReturnValue is true.")] public virtual void NoMethodExceptionWithReturnValueAndTrueIgnoreReturnValue() { ProcessMethod(Methods.TrueIgnoreReturnValueName); } #endregion /////////////////////////////////////////////////////////////////////// #region Static Method Run Tests /////////////////////////////////////////////////////////////////////// [Test, Description("Static method with NO dependencies is run.")] public virtual void NoDependenciesStaticMethodRun() { // Create the attributed type and process it. try { ProcessMethod(Methods.AttributedTypeWithNoDependenciesName); } catch (TargetInvocationException e) { // The "pass" exception will be wrapped in a TargetInvocationException // since we are using reflection throw e.InnerException; } Assert.Fail("Method should have been run and caused this test to pass."); } [Test, Description("Static method with dependencies is run.")] public virtual void DependenciesStaticMethodRun() { // Clear the container to prevent shared state screwing up the tests. // Processing the type will leave the instance stored in the default // instance of the StaticStorageAttribute. var container = StaticStorageAttribute.Default.Container; container.Clear(); // Add the dependencies to be given to the static method. container.Add(new Guid(SetAttributeTests.Ids.FirstName), new BasicContainer(SetAttributeTests.Returns.FirstName)); container.Add(new Guid(SetAttributeTests.Ids.LastName), new BasicContainer(SetAttributeTests.Returns.LastName)); // Create the attributed type and process it. try { ProcessMethod(Methods.AttributedTypeWithDependenciesName); } catch (TargetInvocationException e) { // The "pass" exception will be wrapped in a TargetInvocationException // since we are using reflection throw e.InnerException; } Assert.Fail("Method should have been run and caused this test to pass."); } #endregion /////////////////////////////////////////////////////////////////////// #region Utilities /////////////////////////////////////////////////////////////////////// /// /// Retrieves the method named by from the, /// type returned by grabs the /// first from it, and executes /// on it. /// /// The name of the attributed method. public void ProcessMethod(string methodName) { var type = CreateAttributedMethods(); var method = type.GetMethod(methodName); var attribute = method.GetCustomAttributes(true).First(); attribute.Process(method); } /// /// Holds the attributed methods used for /// testing purposes. /// protected class Methods { /// /// The name of the method. /// public const string AttributedNonStaticName = "AttributedNonStatic"; /// /// The name of the method. /// public const string AttributedTypeWithNoDependenciesName = "AttributedTypeWithNoDependencies"; /// /// The name of the method. /// public const string AttributedTypeWithDependenciesName = "AttributedTypeWithDependencies"; /// /// The name of the method. /// public const string FalseIgnoreReturnValueName = "FalseIgnoreReturnValue"; /// /// The name of the method. /// public const string TrueIgnoreReturnValueName = "TrueIgnoreReturnValue"; /// /// This method will invoke if /// invoked. /// [Run] public void AttributedNonStatic() { Assert.Fail("This method should NOT have been run."); } /// /// This method will invoke if /// invoked. /// [Run] public static void AttributedTypeWithNoDependencies() { Assert.Pass(); } /// /// When invoked, this method verifies that /// is equal to /// and is equal to /// , throwing /// exceptions if they are not. After those are verified /// are invoked. /// /// The same value as /// . /// The same value as /// . [Run] public static void AttributedTypeWithDependencies([Get, Guid(SetAttributeTests.Ids.FirstName)]string firstName, [Get, Guid(SetAttributeTests.Ids.LastName)]string lastName) { firstName.IsEqualTo(SetAttributeTests.Returns.FirstName, SetAttributeTests.Ids.FirstName); lastName.IsEqualTo(SetAttributeTests.Returns.LastName, SetAttributeTests.Ids.LastName); Assert.Pass(); } /// /// Executing the on /// this method will cause an exception to be thrown. /// [Run(IgnoreReturnValue = false)] public static bool FalseIgnoreReturnValue() { return false; } /// /// Executing the on /// this method will NOT cause an exception to be thrown. /// [Run(IgnoreReturnValue = true)] public static bool TrueIgnoreReturnValue() { return true; } } #endregion /////////////////////////////////////////////////////////////////////// #region Overridables /////////////////////////////////////////////////////////////////////// /// /// Creates a type containing attributed /// methods. The type returned should contain the same methods (including /// signature, execution, and attribution) defined by . /// /// The instance containing the attributed methods to be tested. protected virtual Type CreateAttributedMethods() { return typeof(Methods); } #endregion } }