Showing posts with label Visual Studio. Show all posts
Showing posts with label Visual Studio. Show all posts

Wednesday, May 13, 2009

How to test your multi-threaded code (part 3 of 3)?

In the last post we learned how to find and fix a simple multi-thread problem. Now we will see a more complex scenario and see how CHESS wil find the solution.

To do that we will add a ne method to our Account type.

public static void Transfer(double amount, Account fromAccount, Account toAccount)
{
    lock (fromAccount)
    {
        lock(toAccount)
        {
            fromAccount.Withdraw(amount);
            toAccount.Deposit(amount);
        }
    }
}

Because we want to be sure that the transfer works we lock both the “from” and the “to” account.

Now we can easily wrtie this test to see that this is working fine in signle threaded scenario.

[TestMethod]
public void TransferTest()
{
    Account a1 = Account.OpenNew(10000);
    Account a2 = Account.OpenNew(10000);

    Account.Transfer(100, a1, a2);
    Account.Transfer(100, a2, a1);

    Assert.AreEqual(10000, a1.Balance);
    Assert.AreEqual(10000, a2.Balance);
}

As we did before we will convert this single-thread method to a multi-thread one.

[TestMethod]
[HostType("Chess")]
public void TransferMultiThreadTest()
{
    Account a1 = Account.OpenNew(10000);
    Account a2 = Account.OpenNew(10000);

    Thread thread = 
new Thread(o => Account.Transfer(100, ((Account[]) o)[0], ((Account[]) o)[1])); thread.Start(new[] {a1, a2}); Account.Transfer(100, a2, a1); thread.Join(); Assert.AreEqual(10000, a1.Balance); Assert.AreEqual(10000, a2.Balance); }

Now if we run this CHESS will detect a deadlock scenario. If you’ve done some SQL queries you know you should always try to lock all your resources always in the same order. But why doesn’t it working here. We have only one method that lock resources they should be locked in the same order every time, and that’s true. The deadlock occurs because in some cases a thread start to lock the fromAccount (or maybe the toAccount too) and get interrupt by another thread trying to do the same. Then both thread are waiting for each other to complete. Databases engine use timeouts to get out of these situation, but the lock keyword doesn’t support timeout, eventough it uses Monitor.Enter which support it. In another post I will show you how to build your own lock implementation that support timeout, but now we need to find a way to make our code thread safe.

We have to go back to our account class and do some changes.

public static object _locObject = new object();

public static void Transfer(double amount, Account fromAccount, Account toAccount)
{
    lock (_locObject)
    {
        fromAccount.Withdraw(amount);
        toAccount.Deposit(amount);
    }
}

We have to create a static lock object we can use to lock on. Because we are doing the lock in one signle operation our test will now run without any problem.

This is only a small overview of what CHESS can do.

Monday, May 11, 2009

How to test your multi-threaded code (part 2 of 3)?

Previously we saw how to build a test to find a multi-thread bug our your code. Now we will look at how to reproduce debug and fix it.

Remember our bank account class:

public class Account
{
   public double Balance { get; set; }

   private Account(double amount)
   {
       Balance = amount;
   }

   public static Account OpenNew(double amount)
   {
       return new Account(amount);
   }

   public void Deposit(double amount)
   {
       double tempAmount = Balance;
       // potential problem
       lock (this)
       {
           Balance = tempAmount + amount;
       }
   }

   public void Withdraw(double amount)
   {
       double tempAmount = Balance;
       // potential problem
       lock (this)
       {
           Balance = tempAmount - amount;
       }
   }
}

And our test:

[TestMethod()]
[HostType("Chess")]
public void BalanceMutiThreadTest()
{
   Account account = Account.OpenNew(10000);

   Thread thread = new Thread(a => ((Account) a).Withdraw(100));
   thread.Start(account);
   account.Deposit(100);
   thread.Join();

   Assert.AreEqual(10000, account.Balance);
}

Now if we look carefully at the test result detail, there is an explanation on how to reproduce this particular schedule. All you have to do is to copy/paste the code provided just before your test method call.

[TestMethod()]
[HostType("Chess")]
[TestProperty("ChessMode", "Repro")]
[TestProperty("ChessBreak", "BeforePreemption")]
#region ChessScheduleString (not human readable)
[TestProperty("ChessScheduleString", @"bpilaiaaaaaaaaaaaeaaonlnahgabmejjgcfcgcpgnmkhlhpekpfeknhoahekbaiiagabdcenijaeabaommbiimnogjcombngjehcdcjklckibmkgffggffnggbgeammonjnlmphnohloplnphnohloplnphlkdljneochphnpppdpfmgggeabgmpgmoeknkmjjocbiakkmibpdphohmbpdpcchomnfpodnhpidfpappfpfhhpponplpkgpmdelpppbgpkplkpoflfmbopdpkgdppbppfpephpocllfpedhppkopjkppjlohpppohpaaldcaoojfhfaaaaaa")]
#endregion
public void BalanceMutiThreadTest()
{
   Account account = Account.OpenNew(10000);

   Thread thread = new Thread(a => ((Account) a).Withdraw(100));
   thread.Start(account);
   account.Deposit(100);
   thread.Join();

   Assert.AreEqual(10000, account.Balance);
}

(your code may be different)

With that code in place if you run your test again (without the debugger) you will see that only one schedule was evaluated and you got the same result as the previous test. From there, as a tester, you job is done. You check in the code and hand it to the development team. If you are a member of a small team, as I usually am, you may be the tester and the developer so you’ll have to debug the code yourself.

Now run this test again but this time with the debugger. The execution should stop just before one of the lock statement. If you step once you will be able to inspect tempAmount and Balance values and see the problem. Between the line where the debugger stop and the previous line another thread changed the Balance value. Now you can see the don’t match.

Of course in this case the solution is easy, we just have to put the tempAmount assignation inside of the lock block but in the next post you will see a case where the solution is not so obvious.

Tuesday, May 5, 2009

How to test your multi-threaded code (part 1 of 3)?

CHESS is the answer. At least this is what we have best right now.

In multi-threaded application, bug are hard to almost impossible to find. For the last years the only true way to detect threading problems was to run load test until the system crash. Once it does, every once in thousands of iterations, the tools to reproduce and debug the problem were inexistent.

The RiSE (Research in Software Engineering) team at Microsoft have been working for a long time on a product called CHESS. When run with CHESS, you unit tests will try every possible combination of thread interleave to find a case where you application crash or worst doesn’t give you the result you expect.

Here is a simple demo to show you the power of CHESS. Let’s start with a banking account management system.

public class Account
{
    public double Balance { get; set; }

    private Account(double amount)
    {
        Balance = amount;
    }

    public static Account OpenNew(double amount)
    {
        return new Account(amount);
    }

    public void Deposit(double amount)
    {
        double tempAmount = Balance;
        // potential problem
        lock (this)
        {
            Balance = tempAmount + amount;
        }
    }

    public void Withdraw(double amount)
    {
        double tempAmount = Balance;
        // potential problem
        lock(this)
        {
            Balance = tempAmount - amount;
        }
    }
}

Of course I voluntarily introduce “potential problems” to show how CHESS will get them. With that class you can write this test:

[TestMethod()]
public void BalanceTest()
{
    Account account = Account.OpenNew(10000);

    account.Withdraw(100);
    account.Deposit(100);

    Assert.AreEqual(10000, account.Balance);
}

This will always run fine as it is single threaded. Now what if we change it a little to make it multi-threaded:

[TestMethod()]
public void BalanceMutiThreadTest()
{
    Account account = Account.OpenNew(10000);

    Thread thread = new Thread(a => ((Account) a).Withdraw(100));
    thread.Start(account);
    account.Deposit(100);
    thread.Join();

    Assert.AreEqual(10000, account.Balance);
}

As you can see here we put the withdraw part in a new thread. But even then we can run this test again and again without any problem. You can put it in a loop if you want and never being able to make it return an invalid balance.

Once you have CHESS installed on your system the only thing you have to do is to add a HostType attribute to your method.

[TestMethod()]
[HostType("Chess")]
public void BalanceMutiThreadTest()
{
    Account account = Account.OpenNew(10000);

    Thread thread = new Thread(a => ((Account) a).Withdraw(100));
    thread.Start(account);
    account.Deposit(100);
    thread.Join();

    Assert.AreEqual(10000, account.Balance);
}

Now when you run this test you should get something like:

Assert.AreEqual failed. Expected:<10000>. Actual:<10100>.

You should also have noticed that it took a little longer to run the test. This is because the CHESS host scans your code to build an execution schedule for every possible thread interleave that CHESS can detect. If you double click on the test result you will see how many schedules that were tried before finding the bug, in my case it is 3.

Next time we will see how to reproduce and debug that code.

Monday, February 16, 2009

Thursday, December 6, 2007

Debugging Windows Service without deploying it

Have you ever tried to build a Windows Service? Did you get it right the first time? Chances are that you had to modify it a couple of time before getting it the way you want it. Each time you had to build the installation package, uninstall the old version and reinstall the new one. Hopfully you can get the installation package to remove old version before installing new one. How did you debug it? Your only option was to start the service and attache a debugger to it. Although this is a good way to do it and you must go to that process before going into production with your service, this is way too much time consuming for the deveopment process. I invite you to take look at a simple class I built to enable any Windows services to be debug from Visual Studio using F5. Here are the step you have to follow:
  1. Build or open your own Windows Service project
  2. Change it's build setting to be a console application
  3. Add ServiceDebuggerHelper project to your solution (can be download from CodeProject)
  4. Add a reference to ServiceDebuggerHelper project in you project
  5. Modify your Program class to start your service with ServiceRunner if it is started with /debug command line argument
  6. Modify your service to be debuggable in one of two way:
    1. Implement IDebuggableService interface
    2. Inherit from DebuggableService base class
  7. Start it in debug mode

See Debugging Windows Service made easy on CodeProject for details.

Wednesday, November 21, 2007

Quick Tip: Knowing if you are running from visual studio or not

I was trying to know if my program is running from visual studio or not. The reason for that is I want to add a pause in my console application only if it runs from visual studio. Otherwise I want it to run normally.

Here is a quick tip I found. I’m not sure if there is another way to do this but this works fine.

if (AppDomain.CurrentDomain.FriendlyName.Contains(".vshost.")) Console.ReadLine();

If you add this line in a console app, it will wait for a enter only if you un it from visual studio.

Thursday, October 25, 2007

Getting access to Settings in another project

One of the new cool features of Visual Studio 2005 is the new property editor. With this property editor you can easily add setting to your application. But ther is a problem the way its impelemented. Let me explain you why.

Usually the settings are specific to a project. When you add a setting in a project a special custom tool associate with the setting file generates a new class which you can use to access it. What is good about this class is it's strong typed. But behind the scene it's just getting a key from an xml file. This generated class is set as "internal sealed". This prevent from beeing accessed from any other assembly. What if you want to centralize where you edit these settings.

After many attempt to expose it I found a quick an easy way to do it. Let's say we have 2 project in our solution: an Engine and a WinApp. Each have settings but we want them to be editable from WinApp. Here is what it look like.




If you want to get access to Engine settings here th trick: Add a link file.

The link file will be compiled as part as you WinApp project. The setting class will still be internal and sealed but to WinApp project instead of Engine.

Here is the final result:


Notice that I addes a foler with the same name as my Engine project. This will be helpfull if you want to add settings from many projects.

With this in place you can access you engine setting the way from you engine class as from your WinApp class. You may omit the “Engine” part from your engine class because you should be in the same namespace. Here is what it should look like:

namespace WinApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public void AccessConfig()
        {
            Engine.Properties.Settings.Default.EngineSetting = "test";
        }
    }
}