Thursday, December 19, 2013

How to get Ref parameter values in RhinoMock

Mocking ref (and out) parameters with RhinoMock is a bit tedious. I ran into something that could possibly be considered a bug. At the very least it's not really expected behavior. The good news is I found a work-around. Hopefully this will help someone else (including perhaps my future self).

The basic problem is: Ref parameter values passed to mocked methods have the default values specified in the mock setup and not the values passed by the calling code.

The background

Take the following interface as an example.
interface ISomething
{
    void DoStuff(string a);
}
Now supposed this is mocked and some things need to be done based on the value of parameter a.

Normally this is easily done:
public void Initialize()
{
     mockSomething = MockRepository.GenerateStub();
     mockSomething.Stub(s => s.DoStuff(Arg.Is.Anything())
          .Do((Action)(arg =>
               {
                    // Perform general action with arg
                    
                    if (arg == "abc")
                    {
                         // Special case action for arg
                    }
               }));
}
Every time something calls mockSomething.DoStuff, the code passed to the Do method will be executed and the parameter arg will contain whatever value was passed to DoStuff. This is routine stuff for RhinoMocks and works as expected.

The setup

Now suppose the parameter for DoStuff was a ref.
interface ISomething
{
    void DoStuff(ref string a);
}
This is where things get a bit dicey. The interface is still mocked and some things still need to be done based on the value of parameter a. So, some minor syntax changes in the arguments constraints to handle the ref stuff for the compiler are done:
private delegate void DoStuffDelegate(ref string a);

public void Initialize()
{
     mockSomething = MockRepository.GenerateStub();
     mockSomething.Stub(s => s.DoStuff(ref Arg.Ref(Is.Anything(), string.Empty).Dummy)
          .Do((DoStuffDelegate)((ref arg) =>
               {
                    // Perform general action with arg
                    
                    if (arg == "abc")
                    {
                         // Special case action for arg
                    }
               }));
}

The problem

The above code compiles. And it runs. It just doesn't run correctly. The problem is that second parameter in the Arg<T>.Ref method. It indicates a return result for the the value. The problem is RhinoMocks sets the parameter value to the return result before calling Do's method. In other words, in this example, arg will always be string.Empty. The code in Do will never be called with the values sent to DoStuff by the original caller.

Looking at the call stack, I could see the original method call with the correct parameter values. Then it went into the RhinoMock and proxy code and then Do's method was called, clearly with the unexpected value.

Looking for solutions

Digging around, I found the WhenCalled method. This appears to be a bit earlier in the mock/proxy processing so I changed the test.
public void Initialize()
{
     mockSomething = MockRepository.GenerateStub();
     mockSomething.Stub(s => s.DoStuff(ref Arg.Ref(Is.Anything(), string.Empty).Dummy)
          .WhenCalled(invocation =>
               {
                    var arg = (string)invocation.Arguments[0];

                    // Perform general action with arg
                    
                    if (arg == "abc")
                    {
                         // Special case action for arg
                    }
               }));
}
Nope. This didn't work either. The value for Arguments[0] has already been set to the return value.

While searching around, I found other people asking about the same issue. In their cases they found alternative solutions based on constraints of when their methods were called and what values the parameters could have. With known values, constants can be used via hard coding. For example, instead of using Is.Anything() as above, Is.Equal("abc") can be used and the second parameter can be "abc". Everything is fine.

I was semi-successful with the special case by using this technique. But then I needed to do the special action and use Is.NotEqual("abc"). I ran into the same problem as with Is.Anything(). I didn't know the original value for arg.

The solution

Widening my search, I stumbled upon an old article by Ayende talking about the Callback method. He considered it for weird edge case parameter checking and indicated it shouldn't generally be used. As far as I could make out from his write-up, it's purpose is as an alternative to the Arg constraints when they aren't sufficient.

Having nothing to lose, I changed my code to give it a try:
private delegate bool DoStuffCallbackDelegate(ref string a);

public void Initialize()
{
     mockSomething = MockRepository.GenerateStub();
     mockSomething.Stub(s => s.DoStuff(ref Arg.Ref(Is.Anything(), string.Empty).Dummy)
          .Callback((DoStuffCallbackDelegate)((ref arg) =>
               {
                    // Perform general action with arg
                    
                    if (arg == "abc")
                    {
                         // Special case action for arg
                    }

                    return true;
               }));
}
Hurrah! This worked!

Since Callback's intent is to determine if the constraint on the stub is valid, it gets the original parameter values, rather than the return result.

And, yes, I realize I'm misusing the intent of Callback. But when nothing else works, you go with what does.

The conclusion

Since this met my needs, I stopped here. If this was a function rather than a method, I suppose a Do or Return method would have to be chained to the setup code after the Callback method in order to return a valid value for the stubbed function. Also note, if this stub should be ignored, then false can be returned from Callback instead of true. This would allow other stubs for the same method to be handled differently.

I'm not sure if this is a bug, intended behavior or an unconsidered edge case that has, at least to some, unexpected behavior. Both Out and Ref methods have the return result. It makes sense to be mandatory for Out, but I think it should be optional for Ref. I can see cases where you'd want to stub in a particular value all the time. The current syntax supports this well. But I can also see cases where it shouldn't be changed, at least by the Ref handling code. An overloaded version of Ref without the parameter would work well. In any case, I don't think it should be set before WhenCalled and Do are are invoked. At a minimum it should be after and better yet only if the original value hasn't been changed by WhenCalled or Do.

Well, that's my latest story regarding RhinoMocks. I hope it helps someone.

Friday, December 6, 2013

How to generate an alert tone from a computer

I recently read a Code Project thread that got into a discussion about beeps, internal speakers and alerting the user. This reminded me of a story from a previous life...

It was the early 90s and I worked for a company that provided software to E-911 dispatch centers. There was a machine room with racks of computers and then the actual dispatch center which only had user I/O devices. The monitors and keyboards were run through special extension hardware that allowed VGA, keyboard, mouse, serial and parallel ports to be removed from the computer by a fair distance. It seems like the system would drive them up to 100 feet away, but my memory could be faulty. In any case, we had all these extension boxes scattered throughout the center but all the built-in computer speakers were back in the server room.

A feature of the software allowed dispatchers to place calls in a pending queue. This was for low priority calls that didn't have resources available for immediate dispatch. After a timeout, things in the queue would start escalating. First they'd change color. Then they'd start flashing. The Chief wanted the next level to be an audible alert. And, with this being the fire department, audible alert didn't mean a simple "beep." It needed to be impossible to ignore, klaxon-loud and obnoxious. And of course there wasn't any budget for any significant hardware. I thought about it on the drive home and had an idea as I fell asleep.

The next morning I stopped by Radio Shack and picked up a $10 monophonic amplifier. Something simple. (Amazingly, I just searched for it and they still sell the same model 20+ years later, albeit at a slightly higher price.) I also got a 1/8" patch cord and power adapter. When I got to the dispatch center, I cut off one end of the patch cord and connected the leads to the ground and transmit pins on an RS-232 connector on one of the extension boxes. Then I plugged in the amplifier, turned the volume down low, created a short text file with some random characters and cat'ed it to the appropriate /dev/tty port. An earful of noise rewarded my efforts.

Now I knew my idea would work. Playing around with different repeating character sequences gave different patterns. Changing the baud rate would change the frequency. Eventually I came up with a combination that worked pretty well. It was loud, obnoxious and impossible to ignore. The Chief loved it. And it cost less than $20 and an hour or two of work.