This is a pretty interesting approach to a deadlock detector: It uses sos  (son of strike debugger) and automates it under the covers and parses its output to discover runtime deadlocks on processes. At the comments there is a reference to something similar.

Unlike the upcoming Typemock racer (which should be out around mid august), these tools only find deadlocks that occur at runtime, but will not provoke the code into creating deadlocks. that is, the possibility of finding a deadlock that only happens about once in two days in an application using these tools is just about … every couple of days, since it is using the standard process of the application (as far as I can see from the code).

The idea in racer is that it will run all permutations of thread race conditions until it finds a deadlock. so either it finds it, or there isn’t one.

Posted by RoyOsherove

Update: Here is a more full featured declarative example of doing buttons with icons.

OK. Setting icons on your visual studio addins is officially a sucky process and I wish MS would make this a much less painful experience. I cannot believe how much time I have wasted on this.Thanks to Jamie I have a solution for my problems and I’ve added a couple more things.

Problem: You created an addin for VS and you’d like to have custom icons. You google for it and find that it’s not trivial.

Solution: There are a couple of ways to do this. the one I will not show is having a satellite DLL that has the icons resources for the addin. If you are working with VS 2003 as well, you’ll have to do it this way.

Here is the way I’m doing it right now. A lot of this code is from inside testdriven.net’s assemblies (got jamies permission to post this) and I put it in a helper class that I can use easily. In short, you need the following code (will handle .ico and .bmp). see how to use it later below.

using System;

using System.Drawing;

using System.Drawing.Imaging;

using System.Runtime.InteropServices;

using System.Windows.Forms;

using EnvDTE;

using EnvDTE80;

using Microsoft.VisualStudio.CommandBars;

using stdole;

namespace MyAddin1

{

    public class IconUtils

    {

        public static void AddCommandWithicon(Commands2 root,

            CommandBarPopup menuToAddTo,

           string name,

           string buttonText,

           string buttonDescription,

           string iconFile,

           AddIn addInInstance)

        {

            object[] contextGUIDS = null;

            Command command = root.AddNamedCommand2(addInInstance,

                                                        name,

                                                        buttonText,

                                                        buttonDescription,

                                                        true, 59,

                                                        ref contextGUIDS,

                                                        (int)vsCommandStatus.vsCommandStatusSupported +

                                                        (int)vsCommandStatus.vsCommandStatusEnabled,

                                                        (int)vsCommandStyle.vsCommandStylePictAndText,

                                                        vsCommandControlType.vsCommandControlTypeButton);

            CommandBarButton control = (CommandBarButton)command.AddControl(menuToAddTo.CommandBar, 1);

            SetControlPicture(control, iconFile);

        }

 

        private static Color guessTransparentColor(Bitmap bitmap)

        {

            Color pixel = bitmap.GetPixel(0, 0);

            Color color2 = bitmap.GetPixel(bitmap.Width - 1, 0);

            Color color3 = bitmap.GetPixel(0, bitmap.Height - 1);

            Color color4 = bitmap.GetPixel(bitmap.Width - 1, bitmap.Height - 1);

            if (pixel == color2)

            {

                return pixel;

            }

            if (color2 == color3)

            {

                return color2;

            }

            if (color3 == color4)

            {

                return color3;

            }

            return color4;

        }

 

 

        protected static Bitmap PrepareImage(Image image, Color transparentColor)

        {

            Bitmap bitmap = new Bitmap(image);

            Bitmap bitmap2 = new Bitmap(0x10, 0x10, PixelFormat.Format24bppRgb);

            Color color = guessTransparentColor(bitmap);

            for (int i = 0; i < bitmap2.Width; i++)

            {

                for (int j = 0; j < bitmap2.Height; j++)

                {

                    Color baseColor = color;

                    if ((i < bitmap.Width) && (j < bitmap.Height))

                    {

                        baseColor = bitmap.GetPixel(i, j);

                    }

                    baseColor = Color.FromArgb(0xff, baseColor);

                    if (baseColor != color)

                    {

                        bitmap2.SetPixel(i, j, baseColor);

                    }

                    else if ((transparentColor != color) && (baseColor == transparentColor))

                    {

                        if (baseColor.R > 0)

                        {

                            bitmap2.SetPixel(i, j, Color.FromArgb(baseColor.R - 1, baseColor.G, baseColor.B));

                        }

                        else

                        {

                            bitmap2.SetPixel(i, j, Color.FromArgb(baseColor.R + 1, baseColor.G, baseColor.B));

                        }

                    }

                    else

                    {

                        bitmap2.SetPixel(i, j, transparentColor);

                    }

                }

            }

            return bitmap2;

        }

 

        protected static Bitmap PrepareMask(Image image)

        {

            Bitmap bitmap = new Bitmap(image);

            Bitmap bitmap2 = new Bitmap(0x10, 0x10, PixelFormat.Format24bppRgb);

            Color color = guessTransparentColor(bitmap);

            for (int i = 0; i < image.Width; i++)

            {

                for (int j = 0; j < image.Height; j++)

                {

                    Color pixel = bitmap.GetPixel(i, j);

                    Color color3 = ((pixel == color) || (pixel.A < 0xff)) ? Color.White : Color.Black;

                    bitmap2.SetPixel(i, j, color3);

                }

            }

            return bitmap2;

        }

 

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]

        private struct SHFILEINFO

        {

            public IntPtr hIcon;

            public int iIcon;

            public int dwAttributes;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]

            public char[] szDisplayName;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]

            public char[] szTypeName;

        }

 

 

        protected static Icon GetIconFromFile(string path)

        {

            SHFILEINFO psfi = new SHFILEINFO();

            SHGetFileInfo(path, 0x80, ref psfi, Marshal.SizeOf(psfi), 0x111);

            return Icon.FromHandle(psfi.hIcon);

        }

 

 

 

 

        [DllImport("shell32.dll", CharSet = CharSet.Auto)]

        private static extern IntPtr SHGetFileInfo(string pszPath, int dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, int uFlags);

 

 

 

 

        [DllImport("oleaut32.dll", CharSet = CharSet.Auto, SetLastError = true)]

        internal static extern int OleLoadPictureFile(object fileName, [MarshalAs(UnmanagedType.IDispatch)] ref object iPictureDisp);

        static Color VS_MENUCOLOR = Color.FromArgb(0xec, 0xe9, 0xd8);

 

        public static void SetControlPicture(CommandBarButton button,string fileName)

        {

            Image image1 = GetImageFromAnyFormat(fileName);

            Bitmap image2 = PrepareImage(image1, VS_MENUCOLOR);

            Bitmap image3 = PrepareMask(image2);

            button.Picture = CreatePictureDisp(image2);

        }

 

        protected static Image GetImageFromAnyFormat(string path)

        {

            string str = path.ToLower();

            if (str.EndsWith(".exe") || str.EndsWith(".ico"))

            {

                return GetIconFromFile(path).ToBitmap();

            }

            return Image.FromFile(path, true);

        }

 

 

        protected static object OleLoadPictureFile(string fileName)

        {

            object iPictureDisp = null;

            OleLoadPictureFile(fileName, ref iPictureDisp);

            return iPictureDisp;

        }

 

 

        protected static StdPicture CreatePictureDisp(Image image)

        {

            return (StdPicture) ImageConverter.GetIPictureDispFromImage(image);

            //here is another approach:

//            string tempFileName = Path.GetTempFileName();

//            image.Save(tempFileName, ImageFormat.Bmp);

//            return (StdPicture) OleLoadPictureFile(tempFileName);

        }

 

    }

 

    class ImageConverter : AxHost

    {

        // Methods

        internal ImageConverter()

            : base("52D64AAC-29C1-CAC8-BB3A-115F0D3D77CB")

        {

        }

 

        public static IPictureDisp GetIPictureDispFromImage(Image image)

        {

            return (IPictureDisp)AxHost.GetIPictureDispFromPicture(image);

        }

    }

 

 

 

}

 

 

Here is how you can use this code:

Here is what the code in Connect.cs would look if I were creating two buttons with the same icon to the “tools”:

public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)

        {

            _applicationObject = (DTE2)application;

            _addInInstance = (AddIn)addInInst;

            if(connectMode == ext_ConnectMode.ext_cm_UISetup)

            {

                Commands2 commands = (Commands2)_applicationObject.Commands;

                CommandBar menuBarCommandBar = ((CommandBars)_applicationObject.CommandBars)["MenuBar"];

                CommandBarControl toolsControl = menuBarCommandBar.Controls["Tools"];

 

                IconUtils.AddCommandWithicon(commands, (CommandBarPopup)toolsControl,

                    "SomeCommandName",

                    "My Button 1",

                    "Executes the command for MyAddin1",

                    @"c:\a.bmp",

                    _addInInstance);

 

                IconUtils.AddCommandWithicon(commands, (CommandBarPopup)toolsControl,

                    "SomeCommandName2",

                    "My Button 2",

                    "Executes the command for MyAddin1",

                    @"c:\a.bmp",

                    _addInInstance);

            }

        }

 

In the next post I’ll describe how sucky the “command” model is with VS addins and how you can create a somewhatreasonable model for custom actions and buttons that is more maintainable and nderstandable.

image

He was at the zoo today, and all I got was this scary picture. Good parenting, mom!

Posted by RoyOsherove | 2 comment(s)
Filed under:

We've just posted a preview of the next Isolator API coming out in august. It is AAA-style (Arrange, act, assert) and has many changes. We need your input so head on over, read it and tell us your thoughts. This is the time where you can make a huge difference. anything you don't like, say it in the comments.

If you are a reader of this blog and live in Italy (or hong kong)  - that means you live in a place where you can get the new iphone 3g with no sim lock. I have some money in my paypal account that I’d love to give you in exchange for you sending me the device (only Paypal). So, if you’re interested in getting one of them for me and shipping it to Israel, ping me at roy at osherove.com and let me know.

Posted by RoyOsherove | 4 comment(s)
Filed under:

A while ago Udi Dahan wrote that he'd like a way to configure objects by just setting property values on an object. those "setters" will be intercepted and saved to  some config object (or container) for the future use of the application. Here is how simple it is to do with Isolator.

The registration for ALT.NET Israel is now open. You will need an OpenID (I use myopenid.com) to register. We are limited to 50 seats for the first event. First come first served. Worst case scenario you go into the waiting list.

Please only register if you are serious about attending.

The event takes place in two parts: Thursday eve. from 18:.30 to 20.30 and then the full day on friday (9-17.00). more details on the site.

I'm really happy to announce that we are going to have a small (30-70 people) ALT.NET Open Space event in Israel. The full details can be seen on Ken Egozi's blog. Ken is the one who drove Oren and myself into finally getting off our big butts and do this, but he's the one who find the nice location (SQLink offices) and we have Typemock to sponsor food and drinks for the conference.

Registration is not open yet. once the site is ready I will announce it. it is free on a first come first served basis and once we have all the spots filled up you will be put in a waiting list. It will take place on August 7-8 (3 weeks from now!) in Ramat Gan.

In the tradition of open spaces, the first half day (we meet in the evening of thursday) will be devoted to coming up with an agenda for the next day. the next (full day) will be totally run by the attendees. Should be lots of fun!

Here are the current results from the three questions I asked last week. Thanks to all those who answered. If you have not answered yet, it would be great if you took a minute to do so so we can all learn a little something.

What unit test framework do you use?

WindowClipping (2)

The (not so) big surprise is the MS Test is gaining and MvUnit is still way behind on usage compared to NUnit. When MS wants something, it gets it, I guess.

 

What mocking framework do you use?

WindowClipping (3)

Rhino Mocks is far ahead. It seems that, of the some 140 answers, almost the same amount of people don't do testing as there are those that use Moq, with Typemock Isolator, the only Commercial product in the bunch, coming in 3rd (not counting "none" obviously).  It sure is gaining, though. I would have expected more people to be using hand-made mocks and stubs, as that is a very simple way to get started, but that may be a sign that a lot of people may be abusing their mocking framework when they could be having much simpler tests.

 

 

What threading features do you use?

WindowClipping (4)

OK. 550 answer this so far. Far too many people are using Thread.Sleep which may not be the best course of action in many places. We will be using this in our upcoming Typemock Racer to decide which features to support at what order (since we are working incrementally with two week iterations).

I've gotten the chance to visit and consult various companies and I see this all the time: Over specification in tests, especially when doing mocks and stubs.

One main reason for that is that people use their stub as a mock object (stubs are fake objects that we will not assert on so that we can test something else). here is a small example from something posted on the alt.net mailing list:

[Test]

public void Can_Return_All_Plans()

{

IPlanDao mockPlanDao = MockRepository.GenerateMock<IPlanDao>();

mockPlanDao.Expect(x => x.AllPlans(_fakeAdmin)).Return(new List<Plan>{_fakePlan});

PlanController planController = new PlanControllerForTesting(_mockCommonDao, _mockCommonService, mockPlanDao);

ViewResult result = planController.All(false);

mockPlanDao.VerifyAllExpectations();

result.AssertViewResultNameAndViewDataType(typeof(PlanContainer), "Plans");

}

in this test the following line is used to "stub" out a return value into the system under test.

mockPlanDao.Expect(x => x.AllPlans(_fakeAdmin)).Return(new List<Plan>{_fakePlan});

no problem here. The problem lies in the last two lines of the test:

mockPlanDao.VerifyAllExpectations();

result.AssertViewResultNameAndViewDataType(typeof(PlanContainer), "Plans");

 

the second line (the assert) is probably the thing you really want to test. but the call to "verifyAllExpectations" is the one that makes the test very fragile. It is "asserting" that someone has actually called "GetAllPlans()" to get the results, when it clearly does not matter how one got the results. all that matters is that:

"Given a set of results returned into the application under test, the view in the controller is correct" (the translation of the last line in the test).

If by any chance the application later does several more calls to the stubbed out dao, or uses a different method to get results, the test could break, even though the application would still ultimately work with the same end result.

It's like me ordering a pizza delivery and then asking the delivery guy "did you get here by car or motorcycle?" . I realy don't care, as long as the end result: PIZZA, is correct.

So the general rules for me are:

  • If you see both "Verify" and "Assert" in the same test, it is usualy a smell of over specified tests
  • if you see "expect" and "Return" on a fake object, make sure that you name it "stubXX" or "mockXX" so that you can distinguish whether you want to call verify on it later or not(most cases should be "not")
  • Try to test on the end result or end state rather than verify interactions.  The only time you absolutely have not choice but to test an interaction using verify is when calling void methods on external objects. that is clearly a one-way communication and is (or part of)the end result of what you are trying to accomplish.

 

A lot of people think that adding that extra "verify" just means it is a good thing since they are doing more assert. Well, they sure are testing more things, but they are internal things to the app's behavior and that is usually leading to brittle tests. Try to test on the end result or end state rather than verify interactions.

More Posts « Previous page - Next page »