tr ouwens

by the way: things I want to say

Comparing ints and shorts in C#

My colleague Ralph and I recently discovered an interesting bit of C# equality behaviour. Consider the following piece of code:

[Test]
public void Equals()
{
    int i = 42;
    short s = 42;

    Assert.IsTrue(i == s);
    Assert.IsTrue(s == i);
    Assert.IsTrue(i.Equals(s));
    Assert.IsTrue(s.Equals(i)); // fails
}

One would expect the last assert to pass, just like the others. The fact that it doesn’t, tells us two things:

  • The behaviour of == and Equals is different on C#’s primitive integral types. At least, when comparing objects of (slightly) different types.
  • Equals is not symmetric when comparing ints with shorts.

Both are surprising to me. While I don’t like pointing out bugs in things like the .NET Framework (it’s like farting: he who points it out, is usually at fault himself), these do seem to qualify; especially the a-symmetry in Equals, which violates the contract.

There’s probably some arcane piece of .NET legacy at work here, so of course, I sent a question to Eric Lippert. I hope I’ll get a response; I’ll post an update if and when I do.

In the mean time: can you, dear readers, offer an explanation?

A better way of typing

I’m happy! I’m happy because I just found out how to get a Compose key on my shiny MacBook. I want you to be happy too, so I’ll show you how you can get one, too. I’ll even show you how to do it on Windows and Ubuntu. But first, I will explain why this makes me so happy. (If you don’t care about the why, just click here and go straight to the how. But you’ll miss a perfectly good geek-out.)

Why?

I’m a language geek. I like to spell words correctly. Words such as naïveté. Actually, I’m also Dutch, so I have to deal with words like coëfficiënt and of course and (which, really, are two very distinct words). I speak French (or should I say: français) and I live in a country where we pay with . And if that’s not enough, I like to spell people’s names correctly. I’m a software engineer; we’re a pretty international bunch. I’ve worked with people called René, Radovanović, and even Enikő. Yes, that’s an o with a double accent aigu. It’s Hungarian. Try finding that key on your keyboard.

I want it to be easy to type these special characters. I also want it to not get in the way.

Windows has this nifty trick. If you use the US International keyboard layout, you can press a " followed by an e and you automatically get an ë. Sounds nice in theory, but for me, it gets in the way. I’m a programmer; I need to be able to type things like String vowel = "e";. And when I do, I don’t want that to show up like String vowel = ë";. That’s just annoying. On a day to day basis, I have to type "e much more often than I have to type ë.

Of course, if I type a space after I type ", I get my precious ", and I can then type an e and it won’t turn into an ë anymore. I know people, programmers like me even, who have this extra key stroke ingrained in their muscle memory. If they work on a computer where this option is disabled, they type things like String vowel = " e";. Notice the extra space? Now I have nothing against these people, but this is just plain stupid. It’s like hitting your face every five minutes hoping to catch a fly.

OS X has something slightly smarter. To get a special character, you press a special key combination. For example, to get an é, you press ⌥E, followed by e. If you want an ë, you press ⌥U, followed by e. The problem with those combinations is that they’re pretty arbitrary: e for ´, u for ¨, and i for ˆ. In fact, I can never remember what key corresponds to what symbol. It’s not easy.

Also, both methods only support a very limited set of special symbols. Enikő is out of luck; she has to hunt through the Character Map program to spell her name on a non-Hungarian keyboard. If you think that’s too exotic, then you should realise that isn’t directly supported on many systems, either.

I’m not even going to mention Alt codes.

Surprisingly, Linux, for all its usability-issues, has an easy and elegant solution to this mess: the Compose key. You pick a key you don’t use often (I like the Menu key: nobody uses that button anyway) which becomes the Compose key. If you want to enter a special symbol, you hit this button, followed by the two (or more) symbols that you want to ‘compose’. For example, Compose followed by " followed by e becomes ë. Compose followed by = followed by o becomes ő, and Compose followed by = followed by e becomes . Easy!

And it goes even further than that. Combine - and >, and you get an arrow: , T and M become , < and 3 become , and, I was surprised to find out while researching this article, Compose-C-C-C-P becomes . Seriously.

I like this. It doesn’t get in the way at all. I’m free to type String vowel = "e"; without any ë’s showing up. Also, it’s super easy. In fact, it’s so easy that sometimes when I’m bored, I amuse myself by trying out various combinations of keys to see what comes out. How would you type Æ, ¿ or ©?

By now, I have probably convinced you that you want to have a Compose key, too. So how do you get one? It’s easy.

How?

  • OS X: Install the US custom keyboard layout: download and installation instructions are here.
    Note that MacBooks don’t have a Menu key. This tool uses the § key instead, which is fine, because who uses it anyway? And even if you do, it’s a Compose-s-o away.
  • Windows: Install this nifty little program.
  • Ubuntu: Go to System Settings → Keyboard Layout → Options → Compose key position.
  • Any other Linux? Then you probably already know how to do this.

Enjoy a better way of typing! ☺

Foobal: A New Hope

This weekend, a new soccer season started! It’s way past time I told you all how I, or rather, how Foobal did last season.

As you may remember, Foobal started out pretty well. After half a season, it was still doing quite OK. And then… not so much. Unfortunately. Foobal and I finished fourth; a position shared with three other people. In other words: slightly above the middle.

But I shan’t be deterred! This year is going to be better. Actually, I know this for a SOLID FACT, because when I was dusting off the code and preparing the program for the new season, I discovered a bug. A bug that had been there the whole time. A bug that caused Foobal to ignore over 30% of all the data it could have used. A bug that caused foobal to ignore all matches that were played before the 10th of each month.

Oh dear.

How I haven’t seen this sooner, I will never know. It’s not like I didn’t notice many matches were missing from the data file… But here we are.

It turns out that the website I’m scraping my data from, does something unexpected for single-digit dates: it pads them with an extra space. So, instead of mar 2 or mar 02, it actually prints mar  2 in the HTML. Note the extra space between mar and 2.

The code that parses this date, uses a regex that splits on spaces. So in the case of mar 12, it splits into mar and 12, and then passes the 2nd part to the number parsing routine, which is fine. However, in the case of mar 2, it splits into mar,   and 2. And when it passes the 2nd part, which happens to be the empty string, into the number parsing routine, it throws an exception… which promptly gets eaten, never to be seen again. If ever you need an argument for a fail-fast architecture, this is it.

To make matters even more amusing, the entire fix consisted of one. single. character. (OK, I updated some unit tests, too. But still.)

So! This year will be a lot better, I’m pretty sure. Even though Foobal’s first prediction of the season was already incorrect. At least it’s going to be based on much more accurate data.

Testing events in C#

TL;DR

This is a story about the pain of testing events in C#. If you don’t have time to read the whole story, but you are looking for an easy, reliable way to test (asynchronous) events, you can skip straight to the end.

The story

So I’ve been unit-testing events in C# lately, and it’s been kind of a pain. Let’s say we have this code:

public delegate void AnswerHandler(object sender, AnswerEventArgs e);
public class AnswerEventArgs : EventArgs
{
    public int Answer { get; set; }
}

public class AnswerFinder
{
    public event AnswerHandler AnswerEvent;

    public void FindTheAnswer()
    {
        int? answer = DeepThought.Compute();
        if (answer.HasValue)
        {
            var eventArgs = new AnswerEventArgs { Answer = answer.Value };
            AnswerEvent(this, eventArgs);
        }
    }
}

And we want to know whether we got the correct answer. We could write a unit test that looks something like this:

[Test]
public void Attempt1()
{
    var finder = new AnswerFinder();
    finder.AnswerEvent += (sender, e) =>
    {
        Assert.That(e.Answer, Is.EqualTo(42));
    };
    finder.FindTheAnswer();
}

Although—doesn’t this cause a memory leak? Actually, no, because both the producer of, and the subscriber to the event, have the same life cycle and can be garbage collected together. Still, one could argue (and many people do) that it’s good practice to explicitly unsubscribe from the event anyway: that way, you’ve got your bases covered if you do run into a situation where such a memory leak would occur. Or even worse: you could refactor your code, change the scope of either the finder or the event handler, and you forget to update all the places where either of them is used, and voilà: you’ve introduced a memory leak and you didn’t even know it. Better safe than sorry, right?

So now we end up with something like this:

[Test]
public void Attempt2()
{
    var finder = new AnswerFinder();
    EventHandler handler = (sender, e) =>
    {
        Assert.That(e.Answer, Is.EqualTo(42));
    };
    finder.AnswerEvent += handler;
    finder.FindTheAnswer();
    finder.AnswerEvent -= handler;
}

That will do the trick, right? Wrong. There’s no guarantee an answer will be found. DeepThought.Compute() may simply give up at some point and return null, and the event will never be raised. Unfortunately, in that case, our assert is never executed, and the test will happily report success. So we have to guard against that:

[Test]
public void Attempt3()
{
    var finder = new AnswerFinder();
    int answer = -1;
    AnswerHandler handler = (sender, e) =>
    {
        answer = e.Answer;
    };
    finder.AnswerEvent += handler;
    finder.FindTheAnswer();
    Assert.That(answer, Is.EqualTo(42));
    finder.AnswerEvent -= handler;
}

Ouch. Also, what does that -1 mean? Assuming that the answer is always an integer, are we sure it can’t be negative? I’m certainly not. Also, we’re conflating two properties here: whether or not the event was raised, and the actual answer. Let’s fix that.

[Test]
public void Attempt4()
{
    var finder = new AnswerFinder();
    bool eventWasCalled = false;
    AnswerHandler handler = (sender, e) =>
    {
        eventWasCalled = true;
        Assert.That(e.Answer, Is.EqualTo(42));
    };
    finder.AnswerEvent += handler;
    finder.FindTheAnswer();
    Assert.That(eventWasCalled, Is.True);
    finder.AnswerEvent -= handler;
}

That’s an awful lot of boilerplate code for such a simple test! In fact, I’m having trouble seeing the actual test logic through all the boilerplate. Now, imagine if you have a comprehensive test suite with many tests like these. Or actually: please don’t. It makes me sad.

What makes me even sadder, is that DeepThought.Compute() is quite an expensive operation. We don’t want it to freeze the GUI; we should off-load it to a background thread. Great: now we have an asynchronous event. Let’s replace the bool with a ManualResetEventSlim:

[Test]
public void Attempt5()
{
    var finder = new AnswerFinder();
    var resetEvent = new ManualResetEventSlim(false);
    AnswerHandler handler = (sender, e) =>
    {
        resetEvent.Set();
        Assert.That(e.Answer, Is.EqualTo(42));
    };
    finder.AnswerEvent += handler;
    finder.FindTheAnswer();
    Assert.That(resetEvent.Wait(TimeSpan.FromMilliseconds(500)), Is.True);
    finder.AnswerEvent -= handler;
}

OK, that’s not so bad, right? But wait: ManualResetEventSlim implements IDisposable!

[Test]
public void Attempt6()
{
    var finder = new AnswerFinder();
    using (var resetEvent = new ManualResetEventSlim(false))
    {
        AnswerHandler handler = (sender, e) =>
        {
            resetEvent.Set();
            Assert.That(e.Answer, Is.EqualTo(42));
        };
        finder.AnswerEvent += handler;
        finder.FindTheAnswer();
        Assert.That(resetEvent.Wait(TimeSpan.FromMilliseconds(100)), Is.True);
        finder.AnswerEvent -= handler;
    }
}

Of course we could lessen that load by turning resetEvent into a field, and using [SetUp] and [TearDown] methods to initialize it and clean it up. But still a lot of boilerplate remains.

EDIT Are we done? I thought so, but as Ralph correctly pointed out in the comments, this still doesn’t work. If the assert fails, it will throw an exception, yes—but it will do so in the background thread, not in NUnit’s main thread. This means that NUnit doesn’t pick up on it, and the behaviour that follows is undefined. It could report success, or it could fail to terminate at all. The only thing you can be certain of, is that the test won’t actually fail in the way you want. So we have to move the assertion back into the main thread:

[Test]
public void Attempt7()
{
    var finder = new AnswerFinder();
    using (var resetEvent = new ManualResetEventSlim(false))
    {
        int answer = -1;
        AnswerHandler handler = (sender, e) =>
        {
            answer = e.Answer;
            resetEvent.Set();
        };
        finder.AnswerEvent += handler;
        finder.FindTheAnswer();
        Assert.That(resetEvent.Wait(TimeSpan.FromMilliseconds(100)), Is.True);
        Assert.That(answer, Is.EqualTo(42));
        finder.AnswerEvent -= handler;
    }
}

And now, we’re stuck with that nasty -1 again.

Thankfully, we can do better. A lot better.

A solution

I’ve written a small class that uses some clever reflection tricks to handle most of the boilerplate I’ve shown above. Behold:

[Test]
public void FinalAttempt()
{
    var finder = new AnswerFinder();
    AnswerHandler handler = (sender, e) =>
    {
        Assert.That(e.Answer, Is.EqualTo(42));
    };
    using (new EventMonitor(finder, "AnswerEvent", handler))
    {
        finder.FindTheAnswer();
    }
}

Neat, isn’t it? You can find the code below. Maybe I’ll do a proper version on GitHub some day, with its own test suite and proper documentation. Until then, this blog post will have to do :).

Here’s a few things EventMonitor can do:

  • It works both for synchronous and asynchronous events.
  • You can give it a custom timeout in an optional constructor parameter. By default, it’ll wait for 500 milliseconds.
  • Even if you decide not to use the conventional object sender, EventArgs e delegates, it will work with any delegate with up to 4 parameters, as long as they have a void return type.
  • If you want to check that the same event is fired twice, you can do that as follows:
[Test]
public void TheSameEventTwice()
{
    var finder = new AnswerFinder();
    AnswerHandler handler = (sender, e) =>
    {
        Assert.That(e.Answer, Is.EqualTo(42));
    };
    using (var monitor = new EventMonitor(finder, "AnswerEvent",
                                          handler, Mode.MANUAL))
    {
        finder.FindTheAnswer();
        monitor.Verify();

        // Let's do it again!
        finder.FindTheAnswer();
        monitor.Verify();
    }
}

Here’s a few things EventMonitor unfortunately can’t do:

  • Unfortunately, it doesn’t seem possible in C# to pass an event as a parameter. That’s why I opted for the “stringly typed” option of passing the event’s name as a string. If you know of a better way to handle this, I would very much like to hear about it!
  • It’s not fully thread-safe. If you have asynchronous events, and several of them are raised at the same time, EventMonitor’s behaviour will be undefined. If you raise only one asynchronous event, or if you ensure that they aren’t raised simultaneously, it will be fine. This issue could be solved by employing a lock in the Handle method.

Update, October 16th, 2013

Fixed the code, so that it will handle event delegates with primitive type arguments, as well as object type arguments, by adding generics to the solution, as suggested in this StackOverflow question.

Full code of EventMonitor

using System;
using System.Linq;
using System.Reflection;
using System.Threading;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;

namespace Test
{
    public enum Mode
    {
        MANUAL,
        AUTOMATIC
    }

    public class EventMonitor : IDisposable
    {
        private static readonly int MaximumArity = 4;

        private readonly object objectUnderTest;
        private readonly Delegate handler;
        private readonly TimeSpan timeout;
        private readonly Mode mode;

        private readonly ManualResetEventSlim resetEvent;
        private readonly EventInfo eventInfo;
        private readonly Delegate wrappedHandler;

        private Exception exception = null;

        public EventMonitor(object objectUnderTest, string eventName, Delegate handler, Mode mode = Mode.AUTOMATIC)
            : this(objectUnderTest, eventName, handler, TimeSpan.FromMilliseconds(500), mode)
        { }

        public EventMonitor(object objectUnderTest, string eventName, Delegate handler, TimeSpan timeout, Mode mode = Mode.AUTOMATIC)
        {
            this.objectUnderTest = objectUnderTest;
            this.handler = handler;
            this.timeout = timeout;
            this.mode = mode;

            this.resetEvent = new ManualResetEventSlim(false);
            this.eventInfo = objectUnderTest.GetType().GetEvent(eventName);
            Assert.That(eventInfo, Is.Not.Null, string.Format("Event '{0}' not found in class {1}", eventName, objectUnderTest.GetType().Name));

            this.wrappedHandler = GenerateWrappedDelegate(eventInfo.EventHandlerType);
            eventInfo.AddEventHandler(objectUnderTest, wrappedHandler);
        }

        public virtual void Dispose()
        {
            if (mode == Mode.AUTOMATIC)
            {
                Verify();
            }
            eventInfo.RemoveEventHandler(objectUnderTest, wrappedHandler);
            resetEvent.Dispose();
        }

        public void Verify()
        {
            if (exception != null)
            {
                throw exception;
            }
            Assert.That(resetEvent.Wait(timeout), Is.True, string.Format("Event '{0}' was not raised!", eventInfo.Name));
            resetEvent.Reset();
        }

        private Delegate GenerateWrappedDelegate(Type eventHandlerType)
        {
            var method = eventHandlerType.GetMethod("Invoke");
            var parameters = method.GetParameters();
            int arity = parameters.Count();
            Assert.That(arity, Is.LessThanOrEqualTo(MaximumArity), string.Format("Events of arity up to {0} supported; this event has arity {1}", MaximumArity, arity));
            var methodName = string.Format("Arity{0}", arity);
            var eventRegisterMethod = typeof(EventMonitor).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
            if (arity > 0)
            {
                eventRegisterMethod = eventRegisterMethod.MakeGenericMethod(parameters.Select(p => p.ParameterType).ToArray());
            }
            return Delegate.CreateDelegate(eventHandlerType, this, eventRegisterMethod);
        }

        private void Handle(Action action)
        {
            try
            {
                action();
            }
            catch (Exception e)
            {
                exception = e;
            }
            resetEvent.Set();
        }

        private void Arity0()
        {
            Handle(() => handler.DynamicInvoke());
        }

        private void Arity1<T>(T arg1)
        {
            Handle(() => handler.DynamicInvoke(Convert.ChangeType(arg1, arg1.GetType())));
        }

        private void Arity2<T1, T2>(T1 arg1, T2 arg2)
        {
            Handle(() => handler.DynamicInvoke(
                    Convert.ChangeType(arg1, arg1.GetType()),
                    Convert.ChangeType(arg2, arg2.GetType())));
        }

        private void Arity3<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
        {
            Handle(() => handler.DynamicInvoke(
                    Convert.ChangeType(arg1, arg1.GetType()),
                    Convert.ChangeType(arg2, arg2.GetType()),
                    Convert.ChangeType(arg3, arg3.GetType())));
        }

        private void Arity4<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
        {
            Handle(() => handler.DynamicInvoke(
                    Convert.ChangeType(arg1, arg1.GetType()),
                    Convert.ChangeType(arg2, arg2.GetType()),
                    Convert.ChangeType(arg3, arg3.GetType()),
                    Convert.ChangeType(arg4, arg4.GetType())));
        }
    }
}