Want to show your appreciation?
Please a cup of tea.

Friday, July 17, 2009

Intercept Explicit Interface Implementation with Inheritance Based Proxy

This is continue from my last post, Intercept Non-Virtual Interface Implementation, Implicit or Explicit.

Krzysztof was absolutely right that it throws MethodAccessException if you just call it. It only works with delegate. But how difficult and/or expensive it is to use delegate?

  1. For each explicit method that we want to intercept, we need to define a new delegate type that matches the method signature
  2. We need to defined a static field of above generated delegate type for each method
  3. Then we use the static delegate instance to make the call to the explicit implementation method in the parent class

This doesn't sound bad to me. There is nearly no runtime CPU overhead, but to hold the generated delegate types, we need some memory. I believe this is well acceptable. After all, we can further optimized it by caching the generated delegate to be reused by the methods with same signature.

I took this as a good opportunity for me to learn the Reflection.Emit API. Thanks to Krzysztof's for the article Working effectively with Reflection.Emit, which led me to the proper tools and approach to start with. Here is what I have achieved.

        public interface IFoo
        {
            void FooMethod(out int i);
            int BarMethod(int i);
        }

        public class Foo : IFoo
        {
            void IFoo.FooMethod(out int i)
            {
                Console.WriteLine("From Foo.FooMethod!");
                i = 100;
            }

            int IFoo.BarMethod(int i)
            {
                return i*i;
            }
        }

        public static void Main(string[] args)
        {
            const string moduleName = "DynamicModule";
            ModuleBuilder mb = EmitUtils.CreateDynamicModule(moduleName);

            Type t = OverrideFoo(mb);

            var proxy = (IFoo) t.GetConstructor(Type.EmptyTypes).Invoke(null);

            int result;
            proxy.FooMethod(out result);
            Console.WriteLine(result);
            Console.WriteLine(proxy.BarMethod(5));
        }

        private static Type OverrideFoo(ModuleBuilder mb)
        {
            TypeBuilder tb = mb.DefineType(
                mb.Assembly.GetName().Name + ".Bar", 
TypeAttributes.Public | TypeAttributes.Class, typeof(Foo), new Type[]{typeof(IFoo)}); var iFooMethods = typeof (IFoo).GetMethods(); var overriders = new List<ExplicitMethodOverrider>(iFooMethods.Length); foreach (MethodInfo iFooMethod in iFooMethods) { overriders.Add(new ExplicitMethodOverrider(mb, tb, iFooMethod)); } Type t = tb.CreateType(); // Initialize static fields for delegates foreach (ExplicitMethodOverrider overrider in overriders) { overrider.InitializeDelegate(t); } return t; }

The output of above program is:

Proxy before call Void DynamicProxy.Program.IFoo.FooMethod(Int32 ByRef)
From Foo.FooMethod!
Proxy after call Void DynamicProxy.Program.IFoo.FooMethod(Int32 ByRef)
100
Proxy before call Int32 DynamicProxy.Program.IFoo.BarMethod(Int32)
Proxy after call Int32 DynamicProxy.Program.IFoo.BarMethod(Int32)
25

The core of this is consisted of two piece of code. One emits the delegate type based on a the MethodInfo of the explicitly implemented base class method. This is done by a static method EmitUtils.GenerateDelegateType, mostly copy from Joel Pobar. Another one emits a static field of delegate type and implement the interface method to call the delegate, which in turn calls the explicit implementation in the base class. This logic is in the the ExplicitMethodOverrider class on which I spent most of my time. The ExplicitMethodOverrider class also provide an initialization method to populate the static field after the type is created.

All the source code can be found here.

Sunday, July 12, 2009

Intercept Non-Virtual Interface Implementation, Implicit or Explicit

Back in April, I blogged about Rhino Mocks' (Castle DP intrinsic) inability to mock non-virtual interface implementation and posted the question in the Rhino Mocks' support group. I didn't receive much feedback until recently, Krzysztof Koźmic killed a good amount of bugs in the DP and so I tried again. What a coincident that Krzysztof also discussed the same issue in his blog 2 days before I sent him the request. :)

Today, the problem is fixed. But Krzysztof also mentioned two limitations. While the 2nd limitation is well understood, I believe there should be a way to overcome the 1st limitation: calling the explicit implementation method in base class.

The problem reminds me of another challenge that I talked about in my post named, C#.Net Calling Grandparent's Virtual Method (base.base in C#). The lesson learned there was that as long as you can get hold of a MethodInfo object, you should be able to emit the call.

I was able to do similar to successfully call the base class explicit implementation method. Code below is to illustration the theory.

    public interface IFoo { void FooMethod(); }

    public class ThirdParty : IFoo
    {
        void IFoo.FooMethod()
        {
            Console.WriteLine("ThirdParty.FooMethod");
        }
    }

    public class Proxy : ThirdParty, IFoo
    {
        private static readonly Action<ThirdParty> baseFooMethod;

        static Proxy()
        {
            var mi = typeof(ThirdParty).GetMethod(
                typeof(IFoo).FullName.Replace('+', '.') + ".FooMethod", 
                BindingFlags.NonPublic | BindingFlags.Instance);
            baseFooMethod = (Action<ThirdParty>) 
                Delegate.CreateDelegate(typeof(Action<ThirdParty>), mi);
        }

        void IFoo.FooMethod()
        {
            Console.WriteLine("Proxy.FooMethod");
            baseFooMethod(this);
        }

        public static void Main(string[] args)
        {
            IFoo foo = new Proxy();
            foo.FooMethod();
        }
    }

I'm not familiar with Emit API enough to write it out so I'll have to leave the rest to DP expert, Krzysztof Koźmic :)

Update 7/17/2009: I was able to implement this, using delegate, with Reflection.Emit. The result was quite good. It is relatively simple, and has minimal runtime CPU performance overhead. See: Intercept Explicit Interface Implementation with Inheritance Based Proxy

Thursday, July 09, 2009

Some Utilities Extend Rhino.Mocks

I have recently blogged a few posts about how to let Rhino Mocks do more for us. They are listed below:

All those features require reader either change the source code of Rhino Mocks or download a special version of Rhino Mocks that I built. Those changes are quite invasive.

By carefully looking at the code, I found that there are some features can be extract into an extension library without touching the Rhino Mocks itself. Actually, only the ordered expectation requires source code change. Hence, I decided to build a extension library so that everybody can use. You can either drop the source into your test project or download the Rhino.Mocks.Extension.dll and add the reference to it.

Here is the current feature list:

  1. Create multi mock for AAA: Mockery.GenerateMultiMock
  2. Create partial mock for AAA: Mockery.GeneratePartialMock, Mocker.GeneratePartialMultiMock
  3. Ability to use test framework's assert: Assert.IsTrue(mock.ActivityOf(x=>x.Foo()));
  4. Use operator to check "or" condition: mock.ActivityOf(x=>x.Foo()) | mock2.ActivityOf(x=>x.Bar())
  5. Support assert for one and exactly one is called: Mockery.ExactOneOf(m.ActivityOf(...), ...).AssertOccured;

Please see my earlier posts for the detail of feature 3-5.

Wednesday, July 08, 2009

Introduce A Powerful AAA Syntax for Rhino.Mocks

I was again (last one was about ordered expectations for AAA) inspired by a question posted on the Rhino Mocks support email group, expect a call to any one of overloaded method. How do we do that? I have proposed a solution and that was pretty much what I did before. When we talk about TDD, we write the test before implementation. And sometimes, designer writes the test cases for somebody else to complete the implementation.

In many cases, all we care is that one of the send methods of the notification service is called. Which exact send method to call is all up to the implementation.

The Syntax

There got to be a better why to do this! The same may not necessary only apply to overloaded methods. For any methods, I should be able to just write something like this:

    ma.AssertWasCalled(a=>a.Foo()) or mb.AssertWasCalled(b=>b.Bar());

The experience gained from my work on the ordered expectation tells me that this is very possible. All I need to figure out is the syntax for this. May be

    ma.AssertWasCalled(a=>a.Foo()).Or(mb.AssertWasCalled(b=>b.Bar()));

or even better to use operator overload:

    ma.AssertWasCalled(a=>a.Foo()) | mb.AssertWasCalled(b=>b.Bar());

Well, the problem is that AssertWasCalled fails right away when a.Foo() is not called. Why do we have to fail it? Why cannot we leave it to the test framework to do the assert? But anyway, in order to not break the existing contract of AssertWasCalled, we'll have to use something different. How about this?

    Assert.IsTrue(ma.ActivityOf(a=>a.Foo()) || mb.ActivityOf(b=>b.Bar()));

Have more methods, not problem!

    Assert.IsTrue(foo.ActivityOf(a=>a.Foo(Arg<Something>.Is.Anything)) || 
        foo.ActivityOf(a=>a.Foo(Arg<Something>.Is.Anything, Arg<Another>.Is.NotNull)) || 
        foo.ActivityOf(a=>a.Foo(Arg<Something>.Is.Anything, Arg<Another>.Is.NotNull, Arg<int>Is.Anything)));

This syntax give us a lot of flexibility. I can use operator overload for ordered expectation as well.

    Assert.IsTrue(ma.ActivityOf(a=>a.Foo()) < mb.ActivityOf(b=>b.Bar()));

And there are unlimited possibilities, some examples below:

    // chained ordering
(m.ActivityOf(...) > m.ActivityOf(...) > m.ActivityOf(...)).AssertOccured;
    // mixed or ordering
(m.ActivityOf(...) | m.ActivityOf(...)) < m.ActivityOf(...)).AssertOccured
    var sent = (m.ActivityOf(a=>a.Sent(x)) | m.ActivityOf(a=>a.Sent(x, y)));
    Assert.IsTrue(sent); // assert sent is called
    Assert.IsTrue(sent < m.ActivityOf(a=>a.Close())); // assert sent called before close

Implementation

This is exciting, isn't it? How difficult to implement this? I give it a try by building on top of the changes that I made for the ordered expectation in the previous post. It turn out to be quite easy. Although the code below is no where close to perfect, and indeed it is quick and dirty to some extend, but it served well as proof of concept to introduce this technique.

Here we go the code. The Activities class is the core. It provides implementation for all the operator overload.

    public class Activities : IComparable<Activities>
    {
        private static readonly CallRecord[] _emptyRecords = new CallRecord[0];
        private readonly IList<CallRecord> _callRecords = _emptyRecords;
        private readonly ExpectationViolationException _exception;

        public Activities(IList<CallRecord> callRecords)
        {
            if (callRecords == null || callRecords.Count == 0)
                throw new ArgumentException(
                    "Must not be null or empty.", "callRecords");
            _callRecords = callRecords;
        }

        public Activities(ExpectationViolationException exception)
        {
            if(exception==null) throw new ArgumentNullException("exception");
            _exception = exception;
        }

        public bool Occured
        {
            get { return _callRecords.Count > 0; }
        }

        public Activities OccuredBefore(Activities other)
        {
            if (!Occured) return this;
            if (!other.Occured) return other;

            var thisLast = GetLast();
            CallRecord otherFirst = other._callRecords[0];

            return thisLast.Sequence < otherFirst.Sequence ? other
                : new Activities(NewOrderException(thisLast, otherFirst));
        }

        private ExpectationViolationException NewOrderException(
            CallRecord before, CallRecord after)
        {
            return new ExpectationViolationException(
                "Expected that call " + before.Method +
                " occurs before call " + after.Method +
                ", but the expectation is not satisfied.");
        }

        public Activities OccuredAfter(Activities other)
        {
            if (!Occured) return this;
            if (!other.Occured) return other;

            CallRecord otherLast = other.GetLast();
            CallRecord thisFirst = _callRecords[0];
            return otherLast.Sequence < thisFirst.Sequence ? other
                : new Activities(NewOrderException(otherLast, thisFirst));
        }

        public Activities Or(Activities other)
        {
            if (Occured) return this;
            if (other.Occured) return other;
            return new Activities(new ExpectationViolationException(
                this._exception.Message + "\nor\n" + other._exception.Message));
        }

        public Activities First {
            get {
                return Occured ? new Activities(new CallRecord[] {_callRecords[0]}) : this;
            }
        }

        public Activities Last {
            get {
                return Occured ? new Activities(new CallRecord[] { GetLast() }) : this;
            }
        }

        private CallRecord GetLast()
        {
            return _callRecords[_callRecords.Count - 1];
        }

        public int CompareTo(Activities other)
        {
            if (ReferenceEquals(this, other)) return 0;
            return OccuredBefore(other) ? -1 : 1;
        }

        public static implicit operator bool(Activities activities)
        {
            return activities.Occured;
        }

        public static Activities operator <(Activities a1, Activities a2)
        {
            return a1.OccuredBefore(a2);
        }

        public static Activities operator >(Activities a1, Activities a2)
        {
            return a1.OccuredAfter(a2);
        }

        public static Activities operator |(Activities a1, Activities a2)
        {
            return a1.Or(a2);
        }

        public static Activities operator ^(Activities a1, Activities a2)
        {
            return OneOf(a1, a2);
        }

        public static bool operator true(Activities a)
        {
            return a.Occured;
        }

        public static bool operator false(Activities a)
        {
            return !a.Occured;
        }

        public void AssertOccured()
        {
            if (_exception != null) throw _exception;
        }

        internal static Activities ExactOneOf(params Activities[] activitiesList)
        {
            Activities one = null;

            foreach (var activities in activitiesList)
            {
                if (!activities.Occured) continue;
                if (one == null) one = activities;
                else
                    return new Activities(
                        new ExpectationViolationException(
                            "Both " + one._callRecords[0].Method +
                            " and " + activities._callRecords[0].Method +
                            " was called"));
            }
            if (one != null) return one;

            StringBuilder sb = new StringBuilder("None of below is satisfied:");
            foreach (var activities in activitiesList)
            {
                sb.Append('\n').Append(activities._exception.Message);
            }
            return new Activities(new ExpectationViolationException(sb.ToString()));
        }
    }

The other class holds a few extension methods that glues this new API to existing Rhino Mocks.

    public static class Mockery
    {
        public static Activities ActivityOf<T>(this T mock, Action<T> action, 
            Action<IMethodOptions<object>> setupConstraints)
        {
            try
            {
                return new Activities(mock.AssertWasCalled(action, setupConstraints));
            }
            catch (ExpectationViolationException e)
            {
                return new Activities(e);
            }
        }

        public static Activities ActivityOf<T>(this T mock, Action<T> action)
        {
            return ActivityOf(mock, action, DefaultConstraintSetup);
        }

        public static Activities ActivityOf<T>(this T mock, Function<T, object> func, 
            Action<IMethodOptions<object>> setupConstraints)
        {
            return ActivityOf(mock, new Action<T>(t => func(t)), setupConstraints);
        }

        public static Activities ActivityOf<T>(this T mock, Function<T, object> func)
        {
            return ActivityOf(mock, func, DefaultConstraintSetup);
        }

        public static void Assert(Activities activities)
        {
            activities.AssertOccured();
        }

        public static Activities ExactOneOf(params Activities[] activitiesList)
        {
            return Activities.ExactOneOf(activitiesList);
        }

        private static void DefaultConstraintSetup(IMethodOptions<object> options)
        {
        }
    }

You can see that the implementation of the first ActivityOf method is very quick and dirty. The idea was to keep this POC code simple enough to illustrate the technique.

The Failure Message

There is one minor issue with using test framework's Assert.IsTrue. When the assert fails, it simply tells you that you expected true but got false. I don't see this as a big issue because with today's tool you can easily click on the error to jump to the exact line of code. In most of time, the code gives much more information then the message itself. But hey, it is always good to have detailed message right?

Careful reader must already found the Assert method in the Mockery class, that is the one used to replace the Assert.IsTrue. It provides "better" message then true/false. The reason for the quotation marks around the word better is that at this moment, the implementation can sometime provide ambiguous message. Again this is just a POC, in order to provide accurate message, we will need to make deeper changes into the Rhino Mocks.

Below are some examples from the unit test:

            Mockery.Assert(mb.ActivityOf(b => b.Bar()).First
                .OccuredBefore(ma.ActivityOf(a => a.Act()).First)
                .OccuredBefore(mb.ActivityOf(b => b.Bar()).Last));

            (mb.ActivityOf(b => b.Bar()).First
                < ma.ActivityOf(a => a.Act()).First
                < mb.ActivityOf(b => b.Bar()).Last).AssertOccured();
            Mockery.Assert(foo.ActivityOf(f => f.Foo(1)) | 
                foo.ActivityOf(f => f.Foo(Arg<int>.Is.Equal(1), Arg<int>.Is.Anything)));

            (foo.ActivityOf(f => f.Foo(Arg<int>.Is.Equal(1), Arg<int>.Is.Anything)) | 
                foo.ActivityOf(f => f.Foo(1))).AssertOccured();

C# 2.0 / VS2005 Support

It was said that the AAA for C# 2.0 is ugly and tedious. I tried to using this new API with C# 2.0 syntax. The result is not too bad at all. Let's take a look at what we have in the unit test cases:

            Mockery.Assert(Mockery.ActivityOf(ma, delegate(IA a) { a.Act(); }).Last
                .OccuredAfter(Mockery.ActivityOf(mb , delegate(IB b) { b.Bar(); }).Last)
                .OccuredAfter(Mockery.ActivityOf(ma, delegate(IA a) { a.Act(); }).First));

            (Mockery.ActivityOf(ma, delegate(IA a) { a.Act(); }).Last
                > Mockery.ActivityOf(mb, delegate(IB b) { b.Bar(); }).Last
                > Mockery.ActivityOf(ma, delegate(IA a) { a.Act(); }).First).AssertOccured();

            Mockery.Assert(
Mockery.ActivityOf(foo, delegate(IFoo f) { f.Foo(1); }) | Mockery.ActivityOf(foo, delegate(IFoo f) { f.Foo(Arg<int>.Is.Equal(1), Arg<int>.Is.Anything); }));

Give It A Try

If you want to give it a try, I have build a version of Rhino Mocks based on last trunk source with the latest Castle DynamicProxy2 at this moment. You can find them here:

http://code.google.com/p/kennethxublogsource/downloads/list

There are also other features in the build like:

  • Create multi mock for AAA: Mockery.GenerateMultiMock
  • Create partial mock for AAA: Mockery.GeneratePartialMock and Mocker.GeneratePartialMultiMock

Update (7/9/2009): For people don't want a modified version of Rhino.Mocks, I have made an extension library without the feature of ordered expectation: Some Utilities Extend Rhino.Mocks