UnitDriven v0.0.5 Available

http://unitdriven.codeplex.com/releases/view/46068

I applied some updates to UnitDriven and released a new version recently. The updates provide some nicer nesting of namespaces in the test runner UI as well as improved disabling of ‘Run’ buttons and correctly functioning Timeouts.

Also the update is paired with updates to StatLight so you can run your Silverlight unit tests in a purely automated fashion.

Also, if you find yourself trying to remember why you would want to use UnitDriven instead of one of the other unit test frameworks for Silverlight, here are the main features.

  • First class support for asynchronous tests.
  • Supports the ability to author identical tests for Silverlight and .NET (file linking).
  • Parallels either MSTest or NUnit seamlessly.

T4 Text Transformation in MetaSharp

Previously in MetaSharp I had a custom Templating engine for textual transformations. It was a custom grammar and was pretty simple. It worked well and all was good but it was becoming a maintenance burden for me and, I think, turned people off to MetaSharp more than attracted them. So I decided to spend a little time and try to integrate T4 into my templating library as a replacement.

It was actually reasonably simple to accomplish. The hardest part, of course, was working with AppDomains. T4 is a dynamic tool living in a static world and as such it requires an AppDomain to do its magic so it can all be unloaded without a trace. Because of this T4 isn’t very amenable to input. Most examples I found online start with firing up your template then beginning by reading a file or creating a class that connects to a database. In my case I have already have my metadata and would like to pass it into a T4 template but it’s in memory only. The first thing you have to do is make your model Serializable.

Next you need to know about the “inherits” and the “hostspecific” attributes. You add something like this to the top of your template:

<#@ template language="C#" inherits="SongMetaTemplate" hostspecific="true" debug="true" #>

This is for my Song sample application. I then create a SongMetaTemplate class that knows how to cast the model into a Song enumeration.

public abstract class SongMetaTemplate : MetaTemplate
{
    public IEnumerable<Song> Songs
    {
        get { return ((IEnumerable<INode>)this.Model).Cast<Song>(); }
    }
}

Adding a hostspecific attribute to the template causes the template class that inherits from the SongMetaTemplate to also have a Host property which gets loaded up with the Model provided by my pipeline. The MetaTemplate knows how to fetch that host model for me.

public abstract class MetaTemplate : TextTransformation
{
    private object model = null;

    protected object Model
    {
        get
        {
            if (model == null)
            {
                dynamic metame = this;
                var metaHost = metame.Host as MetaSharpTextTemplatingHost;
                if (metaHost != null)
                    this.model = metaHost.Model;
            }

            return model;
        }
    }

    public override string TransformText()
    {
        return this.GenerationEnvironment.ToString();
    }
}

And that’s it! My template can now get a hold of the Song AST parsed from the DSL earlier in the pipeline. Here is an example template in its entirety:

<#@ template language="C#" inherits="SongMetaTemplate" hostspecific="true" debug="true" #>
<#@ assembly name="DynamicSongBuilder" #>
<#@ import namespace="DynamicSongBuilder" #>

<# foreach(var song in this.Songs) { #>
    <# foreach(var b in song.Bars) { #>
        <# foreach(var n in b.Notes) { #>
            play(<#=song.Duration #>, "<#=n.Key #>", <#=n.Octave #>);
        <# }
    }
} #>

The template code is C# but the code generated is actually for my own custom language. In this case it’s parsed into Linq expressions and compiled into a delegate using a context object with a play method. It’s then executed dynamically and also collected by the GC when dereferenced. I plan to replace the custom language also, but its proving difficult without a reasonable parser to replace it.

Silverlight Timer Woes

I was just encountering a bug with using the System.Threading.Timer object in Silverlight for UnitDriven. It was very non-intuitive and sporadic so I thought I’d post some of my conclusions here just in case.

The problem was, that if I had a test that contained a BackgroundWorker that called Thread.Sleep(x) in it’s DoWork event, the timer callback would never get called. I would set the timer to fire in 5 seconds then call sleep for 30. The timer would only fire after the sleep was concluded.

I believe this is the case because Silverlight only has 1 background thread, or at least the Timer and the BackgroundWorker are sharing the same thread. So even though the timers timeout has expired it cannot get CPU time to do the work and fire the callback. The solution I came up with was to, instead of using a timer, simply call Application.Current.RootVisual.BeginInvoke(this.CheckForTimeout) and do the calculation myself. That worked like a charm.

So my conclusion is that getting yourself onto the UI thread in Silverlight is a more reliable way of guaranteeing CPU time since the UI thread is more likely to pumping continuously. Of course too much of that and everything will seem sluggish. What I really need is a backround work queue, or a dispatcher for a background thread in other words.

TypeName Parameterized Rule Test

Here is an example of the types of tests I’ve been writing recently, see if you can figure out what it’s doing:

[Test]
public void TypeNameParameterizedRuleSuccess()
{
    string expected = "a.b.c";
    var stream = new TextStream(expected);

    var list = new Func<PatternMatch, PatternMatch, PatternMatch>(
        (exp, separator) =>
        {
            return Pattern.And(
                exp,
                Pattern.ZeroOrMore(
                    Pattern.And(
                        separator,
                        exp)));
        });

    var pattern = Pattern.Projection(
        list(
            Pattern.Range('a', 'z'),
            Pattern.Value('.')),
        match => match.AsString());

    var actual = pattern(stream);
    Assert.AreEqual(expected, ((ValueNode)actual).Value);
}

beautiful!

Thoughts on Parallel Parsing

same-operations

I don’t have much time today but this was a quick sketch I made when talking to a friend about parallel parsing. This is related to considering parsing each item in an OR expression in parallel. It would incur a lot of locking in order to safely share memo tables but if you don’t share memo tables you end up with a lot of duplicate effort.

But I wonder, is duplicate effort actually bad in parallel?