2011/05/22

Delegates serialization: Limits

When I heard about delegates’ serializability for the first time, my reaction was romantic. I dreamt about some mystical process that serializes delegate’s IL and about other magical things. It is, of course, absolute nonsense, but I love those fairy tales :).

All delegates in C# are inherited directly or indirectly from Delegate. Delegate class is class like any other. It is just marked as serializable – no black magic is needed.

What is buried there?

Basically, there are two properties: Method (MethodInfo) and Target (object). It is all what is needed to invoke any .NET method. When delegate points to a static method, then the Target property is null. There are some other internal details that I don’t understand but I hope they are irrelevant.

These facts reveal weaknesses of delegates’ serialization:
  1. Target property is serialized as well when using binary formatter. It could lead some serious issues when object referenced by Target is part of complex object graph. On the other side if Target is not serialized then the delegate cannot be deserialized at all – there wouldn’t be any suitable instance to make a method call.
  2. Versioning issues.
  3. State of static class is not serialized. Delegate of method that is using static fields (directly or indirectly) is deserialized into completely different context.
In addition to these disadvantages, there is a limitation associated with anonymous delegate that is closed over a variable. It is simply not serializable.

It is clear that “persistable continuation” implemented in C# by delegate serialization as it was suggested by Mike Hadlow would be very limited, which is a pity.

2011/05/15

NHibernate: Serializing Delegates

Mike Hadlow discovered very interesting delegate feature for me. They are serializable! In outher words they can be stored in a database, e.g. with NHibernate.

Entity that represents a persistable entity could look like this:
public class PersistableDelegate
{
    public virtual Delegate Delegate { get; set; }
    public virtual string Name { get; set; }
    public virtual int Id { get; set; }

    private byte[] SerializedDelegate {
        get {
            if (Delegate == null)
                return null;

            var formatter = new BinaryFormatter();
            using (var stream = new MemoryStream()) {
                formatter.Serialize(stream, this.Delegate);
                return stream.ToArray();
        }

        set {
            if (value != null) {
                var formatter = new BinaryFormatter();
                using (var stream = new MemoryStream(value))
                    Delegate = (Delegate)formatter.Deserialize(stream);
            }
            else
                Delegate = null;
        }
    }
}

Your model can manipulate with Delegate property. SerializedDelegate property provides access to serialized data of the delegate for NHibernate – it is implementation detail and is marked as private. Getter of this property returns the delegate serialized to an array and the setter reconstructs the delegate from provided data.

FNH mapping is simple as breath then:
public class PersistableDelegateMap : ClassMap<PersistableDelegate> {
    public PersistableDelegateMap() {
        Id(x => x.Id);
        Map(x => x.Name);
        Map(Reveal.Member<PersistableDelegate>("SerializedDelegate"))
            .Length(int.MaxValue);
    }
}
Reveal class makes it possible to map private property.

Corresponding database table for MS SQL is:
CREATE TABLE [dbo].[PersistenceAction](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](255) NULL,
    [SerializedDelegate] [image] NULL,
)

Now it is possible to store a delegate in database:
var action = new PersistableDelegate();
action.Delegate = (Action)(() => { Console.WriteLine("Hello from persisted delegate!"); });
action.Name = "First test";

session.Save(action);
session.Flush();

and load back:
var action = session.Query<PersistableDelegate>().Where(x => x.Name == "First test").FirstOrDefault();
action.Delegate.DynamicInvoke();

I am not sure yet how can be this useful. There are definitely many limitations, e.g. lambda expression closed over local variable is not serializable. In any case such feature is very promising...

2011/04/18

Integration tests, NHibernate and Sqlite, part 3 – enhanced in memory database

Integration tests, NHibernate and Sqlite, part 1
Integration tests, NHibernate and Sqlite, part 2 – in file database
Integration tests, NHibernate and Sqlite, part 3 – enhanced in memory database

In previous post I introduced a database scope that builds the database schema only once per test suit run. Some performance was sacrificed to achieve this: the database had to be stored in a file. Database stored in memory is obviously faster than database stored in a file. Is there a way how to move the database back to memory?

Yes, we can build a master database in-memory and then make copy of this master database for each test. The problem is how to duplicate the master database. Sqlite provides Online Backup API, which is not available in System.Data.SQLite wrapper yet.

Sqlite Backup API
Fortunately it is quite easy to wrap the required API:
[DllImport("System.Data.SQLite.DLL", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr sqlite3_backup_init(IntPtr destDb, byte[] destname, IntPtr srcDB, byte[] srcname);

[DllImport("System.Data.SQLite.DLL", CallingConvention = CallingConvention.Cdecl)]
internal static extern int sqlite3_backup_step(IntPtr backup, int pages);

[DllImport("System.Data.SQLite.DLL", CallingConvention = CallingConvention.Cdecl)]
internal static extern int sqlite3_backup_finish(IntPtr backup);

public static void Backup(SQLiteConnection source, SQLiteConnection destination)
{
    IntPtr sourceHandle = GetConnectionHandle(source);
    IntPtr destinationHandle = GetConnectionHandle(destination);

    IntPtr backupHandle = sqlite3_backup_init(destinationHandle, SQLiteConvert.ToUTF8("main"), sourceHandle, SQLiteConvert.ToUTF8("main"));
    sqlite3_backup_step(backupHandle, -1);
    sqlite3_backup_finish(backupHandle);
}

There is only one catch. Handles needed by Sqlite API are stored as private fields in System.Data.SQLite wrapper. But it can be retrieved by this little trick:
private static IntPtr GetConnectionHandle(SQLiteConnection source)
{
    object sqlLite3 = GetPrivateFieldValue(source, "_sql");
    object connectionHandle = GetPrivateFieldValue(sqlLite3, "_sql");
    IntPtr handle = (IntPtr)GetPrivateFieldValue(connectionHandle, "handle");

    return handle;
}

private static object GetPrivateFieldValue(object instance, string fieldName)
{
    var filedType = instance.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);

    object result = filedType.GetValue(instance);
    return result;
}

Yes, it is a hacky solution but it works well and it can be viewed as temporary replacement for the missing wrapper part.

SqliteInMemoryPrivateScope
Modification of SqliteInFilePrivateScope is easy with such helper method.

The master database is duplicated by the new wrapper method:
public SqliteInMemoryPrivateScope()
{
    EnsureMasterDatabaseExistence();

    this.privateConnection = new SQLiteConnection(connectionString);
    this.privateConnection.Open();

    SqliteBackup.Backup(masterConnection, this.privateConnection);
}

And a connection to the master database must be held by the scope instance. It is similar to SqliteInMemorySharedScope:
private static SQLiteConnection masterConnection;

private void EnsureMasterDatabaseExistence()
{
        // to support asynchronous scenario
        lock (configurationSync) {
            if (configuration == null) {
                configuration = BuildConfiguration ();
                sessionFactory = configuration.BuildSessionFactory();

                masterConnection = new SQLiteConnection(connectionString);
                masterConnection.Open();

                SchemaExport schemaExport = new SchemaExport(configuration);
                schemaExport.Execute(false, true, false, masterConnection, TextWriter.Null);
            }
        }
}

Now we have a database scope that builds configuration, session factory and database schema only once per test suit run which saves a lot of time. In addition the database is stored in memory so integration tests run blazingly fast. The isolation between tests is very good and the test can be executed in parallel. What to want more?:).

Full implementation of SqliteInMemoryPrivateScope can be found here.
Complete source code can be downloaded here.

2011/04/11

Integration tests, NHibernate and Sqlite, part 2 – in file database

Integration tests, NHibernate and Sqlite, part 1
Integration tests, NHibernate and Sqlite, part 2 – in file database
Integration tests, NHibernate and Sqlite, part 3 – enhanced in memory database

SqliteInMemorySharedScope issues
The disadvantage is that the time needed byc SqliteInMemorySharedSope instantiation grows with the size of the tested domain model. When the domain model is complex enough then execution of test suit may take unacceptable amount of time.

Storing the database in a file
Sqlite is able to store the database in a file as well. We create a database with its schema at first and store it in a file, let’s call it master file. Then it is easy to create a copy of the master file. Individual tests touch only own copy of the master file. So isolation is preserved and dependency between the time of database scope instantiation and complexity of the domain is significantly more moderate.

SqliteInFileDatabaseScope
The new session is connected to the private copy of the master file.
public ISession OpenSession()
{
    ISession session = SqliteInFilePrivateScope.sessionFactory.OpenSession(this.privateConnection);

    return session;
}

The private connection is created in the default constructor.
public SqliteInFilePrivateScope()
{
    EnsureMasterDatabaseExistence();

    // to avoid name collisions in parallel scenario
    this.privateDatabaseFileName = Guid.NewGuid().ToString() + ".db";

    File.Copy(masterDatabaseFileName, this.privateDatabaseFileName);

    string connectionString = BuildConnectionString(this.privateDatabaseFileName);
    this.privateConnection = new SQLiteConnection(connectionString);
    this.privateConnection.Open();
}

The master file, configuration and session factory are created only once per test suit run.
private static object configurationSync = new object();

private void EnsureMasterDatabaseExistence()
{
    // to support parallel execution of unit tests
    lock (configurationSync) {
        if (configuration == null) {
            string connectionString = BuildConnectionString(masterDatabaseFileName);
            configuration = BuildConfiguration(connectionString);
            sessionFactory = configuration.BuildSessionFactory();

            SchemaExport schemaExport = new SchemaExport(configuration);
            schemaExport.Execute(false, true, false); 
        }
    }
}

Connection string factoring:
private static string BuildConnectionString(string databaseName)
{
    return string.Format("Data Source={0};Version=3;New=True;", databaseName);
}

And BuildConfiguration is delegate that is injected on test suit initialization (for more details see this post):
public static Func<string, NHibernate.Cfg.Configuration> BuildConfiguration;

The full example is here.
The same example but using Microsoft Sql Server Compact Edition instead of Sqlite is here.
Complete source code can be downloaded here.

Why to support parallel scenarios in Visual Studio 2010
Tests are executed sequentially by default in Visual Studio and there is no setting to turn on parallel execution in VS2010 GUI. To achieve this, the file with test settings must be tweaked. The name of the file is Local.testsetings by default:
<TestSettings name="Local" id="caf44e0f-3ee4-46bf-a6ed-73aea6d93533" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
  <Description>These are default test settings for a local test run.</Description>
  <Deployment enabled="false" />
  <Execution parallelTestCount="2">
    <TestTypeSpecific />
    <AgentRule name="Execution Agents">
    </AgentRule>
  </Execution>
</TestSettings>

Attribute parallelTestCount specifies how many tests are executed at one time. Parallel execution makes sense in these days of multicore processors because it can reduce the execution time of whole test suit. And it counts when doing continuous integration. You can find much more information in this blog post.

2011/04/04

Unit tests initialization in Visual Studio 2010

NHDatabaseScopes problem
I am going to dig into a nasty detail of SqliteInMemorySharedScope class in this post. The FNH configuration is built by the constructor of this class. NH configuration needs to know which assembly to load the mapping metadata from. If the knowledge is included right in the constructor then the SqliteInMemorySharedScope (like in previous post) is coupled with tested domain model and cannot be reused in other project. It would be neat to inject the metadata or just the configuration into it. The configuration and session factory is shared between all unit tests and there is usually no particular execution order defined for tests. The question is: how to inject all information needed by SqliteInMemorySharedScope?

Unit test initialization
VS2010 offers a way how run a code before any test is executed. Just decorate a static method in test class with AssemblyInitialize attribute:
[TestClass]
public class TestEnvironmentInitialization
{
   [AssemblyInitialize]
   public static void Initialize(TestContext context)
   {
      // any initialization code

Some code can be executed after all tests were finished as well – attribute AssemblyCleanup.
The execution order is:
1)    Static method marked by AssemblyInitialize attribute.
2)    Default constructor of a test class.
3)    Method marked by TestInitialize attribute.
4)    Method marked by TestMethod attribute.
5)    Method marked by TestCleanup attribute.
6)    Static method marked by AssemblyCleanup attribute.

SqliteInMemorySharedScope decoupling from domain model
Back to the SqliteInMemorySharedScope class. A delegate that builds NH configuration is injected instead of configuration itself. The advantage, but questionable, is lazy initialization. Configuration is built only when it is really needed.
SqliteInMemorySharedScope initialization:
[TestClass]
public class TestEnvironmentInitialization
{
    private static NHibernate.Cfg.Configuration BuildSqliteConfiguration(string connectionString)
    {
    var config = Fluently.Configure()
        .Database(SQLiteConfiguration.Standard.ConnectionString(connectionString))
        .Mappings(m => {
            m.FluentMappings.AddFromAssembly(typeof(Order).Assembly);
        })
        .BuildConfiguration();

    return config;
}

[AssemblyInitialize]
public static void Initialize(TestContext context)
{
    BuildConfiguration = BuildSqliteConfiguration;

And simple modification of SqliteInMemorySharedScope:
public class SqliteInMemorySharedScope
{
    public static Func<string, NHibernate.Cfg.Configuration> BuildConfiguration;

   public SqliteInMemorySharedScope()
   {
      if (configuration == null) {
         configuration = BuildConfiguration(connectionString);
      }
SqliteInMemorySharedScope is decoupled from the domain model now and can be reused in multiple projects.

Source code can be downloaded here.

2011/03/29

Integration tests, NHibernate and Sqlite, part 1

Integration tests, NHibernate and Sqlite, part 1
Integration tests, NHibernate and Sqlite, part 2 – in file database
Integration tests, NHibernate and Sqlite, part 3 – enhanced in memory database

Source code can be downloaded here.

Purpose of unit test is to determine if specific unit of code fits for its use. Units are the smallest testable parts of a system. Integration tests evaluate that unit or subsystem is well integrated with other units or subsystems.  NHibernate is quite large and complex system and if you use it in your test then it is an integration test – your test evaluates, among other things, that the unit (or something larger) plays well with NH. That is the reason why I will use integration tests term in this post, although somebody may disagree:).

Embedded databases are suitable for integration testing. It is mainly for performance and deployment reasons. Such well established and popular database is Sqlite which has some interesting features and I will use it in this post.

To test something with NHibernate we need some domain model. Since my imagination is not very playful, I will use very ordinary “Order” example:
    public class Order
    {
        public Order()
        {
            Rows = new Iesi.Collections.Generic.HashedSet<OrderRow>();
        }

        public virtual int Id { get; set; }
        public virtual string ShipName { get; set; }
        public virtual DateTime RequiredDate { get; set; }

        public virtual Iesi.Collections.Generic.ISet<OrderRow> Rows { get; set; }
    }

    public class OrderRow
    {
        public virtual int Id { get; set; }
        public virtual decimal Price { get; set; }
        public virtual string Product { get; set; }
    }

Mapped with Fluent NHibernate:
    public class OrderMap : ClassMap<Order>
    {
        public OrderMap()
        {
            Id(x => x.Id);

            HasMany(x => x.Rows).Cascade.AllDeleteOrphan();
            Map(x => x.RequiredDate);
            Map(x => x.ShipName);
        }
    }

    public class OrderRowMap : ClassMap<OrderRow>
    {
        public OrderRowMap()
        {
            Id(x => x.Id);

            Map(x => x.Price);
            Map(x => x.Product);
        }
    }

Naive implementation
It is a boring and useless example. But we need just something to feed NHibernate and the domain model could be even a little bit simpler and more useless than this crap.

We build NH configuration, session factory and database schema before each test:
 string connectionString = "Data Source=:memory:;Version=3;New=True;";

var config = Fluently.Configure()        
         .Database(SQLiteConfiguration.Standard.ConnectionString(connectionString))
         .Mappings(m => {
             m.FluentMappings.AddFromAssembly(typeof(Order).Assembly);
         })
         .BuildConfiguration();

var sessionFactory = config.BuildSessionFactory()

var connection = new SQLiteConnection(connectionString);
connection.Open();

// build the database schema
var schemaExport = new SchemaExport(config);
schemaExport.Execute(false, true, false, connection, TextWriter.Null);

// voiala, session is ready for the test
var session = sessionFactory.OpenSession(connection);
There is something worth noting in this code. Sqlite cleans up in-memory database when all connections to that database are closed. This is the reason why the connection is explicitly opened and then provided to Execute and OpenSession methods. The database would be empty without this connection sharing.

Everything goes nice. Tests are pretty good isolated because they receive own database – they run in own sandboxes and cannot cause any harm by destroying data needed by other tests.
Some troubles will appear as soon as the domain complexity and number of integration tests get a little bit higher. Building configuration, session factory and database schema may take several seconds and execution time of test suit may become intolerable very quickly.

Speedup
It would be nice to do time consuming operation only once per a test suit run. Two things can be shared between tests without losing advantages of test isolation: NH configuration and session factory. This can save significant amount of time. The database still must be created for each individual test.

Here is the complete example factored into class:
public class SqliteInMemorySharedScope
{
    private static ISessionFactory sessionFactory;
    private static NHibernate.Cfg.Configuration configuration;
    private static IDbConnection connection;

    private const string connectionString = "Data Source=:memory:;Version=3;New=True;";


    public SqliteInMemorySharedScope()
    {
        if (configuration == null) {
            configuration = Fluently.Configure()
                .Database(SQLiteConfiguration.Standard.ConnectionString(connectionString))
                .Mappings(m => {
                    m.FluentMappings.AddFromAssembly(typeof(Order).Assembly);
                })
                .BuildConfiguration();
        }

        if (sessionFactory == null)
            sessionFactory = configuration.BuildSessionFactory();

        if (connection == null)
            connection = new SQLiteConnection(connectionString);


        var schemaExport = new SchemaExport(configuration);
        schemaExport.Execute(false, true, false, connection, TextWriter.Null);
    }

    public ISession OpenSession()
    {
        ISession session = sessionFactory.OpenSession(connection);

        return session;
    }
}
And here is how to use that:
var scope1 = new SqliteInMemorySharedScope();
using (var session1 = scope.OpenSession()) {
    var row = new OrderRow() {
        Product = "Product1",
        Price = 10,
    };

    session1.Save(row);
    session1.Flush();
}

var scope2 = new SqliteInMemorySharedScope()
using (var session2 = scope2.OpenSession()) {
    Assert.AreEqual(0, session2.CreateQuery("from OrderRow").List().Count);
}
The configuration and session factory are built when scope1 is instantiated. When scope2 is created then only database schema must be established again.

Why SqliteInMemorySharedScope?
Sqlite – Sqlite database engine.
InMemory – database is stored in-memory.
Shared – connection is shared between all scopes.

There must be a better naming scheme but I am not able to find anything that is reasonable. Any idea?