James's profileJames McCaffreyBlogLists Tools Help

Blog


    December 29

    Restarting a Remote Machine not on the Current Domain

    Recently I needed to restart a remote test host machine. If you want to restart a remote machine which is on the same domain as the local machine you are going to use to issue the restart command, then you can use the normal shutdown.exe command line utility:
     
    C:\localmachine> shutdown.exe /r /m \\remotemachinename
     
    Or, if the remote machine you want to restart has Remote Desktop enabled, then you can remote in using the mstsc.exe utility (Start -> Run -> mstsc -> <enter>) and then either simply click Start -> Shut Down -> Restart if that option is available, or do a <CTRL>-<ALT>-<END> to get a restart dialog box. But what if the remote machine is neither on the same domain as your local machine, nor accessible via Remote Desktop? One way to restart such a remote machine is to use the net use command to connect to the remote machine, and then use shutdown. For example, suppose you want to restart some machine which has IP address 222.111.33.444 from your local machine. The scenario could resemble:
     
    C:\localmachine> ping 222.111.33.444
    Reply from 222.111.33.444: bytes=32 time=32ms TTL=116
    Reply from 222.111.33.444: bytes=32 time=32ms TTL=116
    ^C
    C:\localmachine> net use \\222.111.33.444\c$
    Enter the user name for '222.111.33.444': administrator
    Enter the password for 222.111.33.444: ********
    The command completed successfully
    C:\localmachine> shutdown.exe /r /m \\222.111.33.444
     
    And the remote machine will restart after the default delay of 30 seconds. Finally you can clean up with:
     
    C:\localmachine> net use \\222.111.33.444\c$ /delete
    \\222.111.33.444\c$ was deleted successfully.
    C:\localmachine> _
     
    There you have it. Like many things, easy and obvious once you know how to do it, but not so easy or obvious if you don't know how.
     
    December 23

    Test Case Input Symmetry

    I ran across an interesting effect recently. The effect is related to symmetry in test case input. The bottom line is that when you are testing you cannot assume the sending inputs (a,b) to some system under test is the same as sending inputs (b,a) to the system. This is true even when the system under test should treat inputs the same, for example, a sum(x,y) function. I was looking at a Poker Library. One of the methods in the library is a Hand.Compare(h1,h2) which compares poker hands h1 and h2, returning -1 if hand h1 is worse than hand h2, returning 0 if the hands tie, and returning +1 if hand h1 is better than hand h2. For example Hand.Compare("Ac Ad Ah 9c 9d", "Kc Kd Qh Qs 2c") returns +1 because a full house aces over nines is better than two pair kings over queens. When testing such a method you cannot assume that if this test case passed, that Hand.Compare("Kc Kd Qh Qs 2c", "Ac Ad Ah 9c 9d"), that is the same inputs but with order reversed, with an expected value of -1 would also pass. This principle -- that you must test all permutations of input arguments -- is pretty well known, but I see even experienced testers neglect it every now and then.
    December 12

    Rule Sets and Automatic Software Test Case Generation

    The other day I had a strange idea about a possible way to automatically generate test case data. Automated test case generation is one of the Holy Grails of testing. It is relatively easy to generate test case input but very  difficult to generate expected results. One approach is to feed random input to a system under test to try and produce a fatal state; this technique doesn't need an expected result (the implied result is that he SUT doesn't crash). Another approach to automated software test case generation is to decorate the system under test with all kinds of pre-conditions and post-conditions, and then have some relatively sophisticated tool generate both test case inputs and expected values from the pre- and post- condition information. See for example Pex at http://www.sqaplanet.com/aggregator/sources/53. Another approach is various forms of model based development. For example, you create some model using UML (which contains pre-conditions and post-conditions) or similar meta-language which in turn can generate source code and test cases. Anyway, my idea is to use an evolutionary algorithm approach for automated test case generation for certain types of systems. Imagine a SUT with four input parameters, A, B, C, D. Input parameter A is discrete and can take on one of three values: a1, a2, a3. Similarly, B can be b1, b2, b3. C can be c1, c2. D can be d1, d2. Suppose the SUT can transition to one of three states, s1, s2, s3. There are a total of 3 * 3 * 2 * 2 = 36 inputs which could easily be handled but I'll illustrating with a small example. Now consider a rule based system. One rule might be "if a1 and c2 then s3". There are a total of 131 possible rules for this example. My idea is to manually list a relatively small set of training rules, and then use an evolutionary algorithm such as a Genetic Algorithm or Simulated Annealing to produce a set of rules from all possible rules. These rules could then be used to generate test case expected results. The results wouldn't be perfect; more along the line of input = {a1, b2, c1, d2}, output = {s2} => possible test case failure according to generated rule set. I have no idea if anyone has investigated such an idea before.
     
    December 08

    A Gray Code Mini-Library in C#

    In my last blog entry I described how I recently needed a set of Gray Code conversion routines in the C# language. Here is the mini-library I wrote. First, my library assumes an 8-bit system, which can represent unsigned integers in the range 0 to 255. Second, the bit representation of an integer is an 8-cell int array, where each array holds 0 or 1. Third, the bit representation stores the least significant bit at array index [0], and the most significant bit at array index [7].
     
    static int[] IntToBinary(int n)
    {
      int[] binary = new int[8];
      int i = 0;
      do {
        binary[i++] = n % 2;
      } while ((n /= 2) > 0);
      return binary;
    }
     
    static int BinaryToInt(int[] binary)
    {
      int ans = 0;
      for (int i = 0; i <=7; ++i) {
        ans = ans + (int)Math.Pow(2, i) * binary[i];
      }
          return ans;
    }
     
    static int[] BinaryToGray(int[] binary)
    {
      int[] gray = new int[8];
      gray[7] = binary[7]; // copy high-order bit
      for (int i = 6; i >= 0; --i) { // remaining bits
        if (binary[i] == 0 && binary[i + 1] == 0)
          gray[i] = 0;
        else if (binary[i] == 1 && binary[i + 1] == 1)
          gray[i] = 0;
        else if (binary[i] == 0 && binary[i + 1] == 1)
          gray[i] = 1;
        else if (binary[i] == 1 && binary[i + 1] == 0)
          gray[i] = 1;
      }
      return gray;
    }
     
    static int[] GrayToBinary(int[] gray)
    {
      int[] binary = new int[8];
      binary[7] = gray[7]; // copy high-order bit
      for (int i = 6; i >= 0; --i) { // remaining bits
        if (gray[i] == 0 && binary[i + 1] == 0)
          binary[i] = 0;
        else if (gray[i] == 1 && binary[i + 1] == 1)
          binary[i] = 0;
        else if (gray[i] == 0 && binary[i + 1] == 1)
          binary[i] = 1;
        else if (gray[i] == 1 && binary[i + 1] == 0)
          binary[i] = 1;
      }
      return binary;
    }
     
    static int[] IntToGray(int n)
    {
      int[] binary = IntToBinary(n);
      int[] gray = BinaryToGray(binary);
      return gray;
    }
     
    static int GrayToInt(int[] gray)
    {
      int[] binary = GrayToBinary(gray);
      int n = BinaryToInt(binary);
      return n;
    }
     
    static void showBitsInMemory(int[] bits)
    {
      Console.Write("[");
      for (int i = 0; i < bits.Length; ++i) {
        Console.Write(bits[i] + " ");
      }
      Console.WriteLine("]");
    }
     
    static void showBitsStandard(int[] bits) 
    {
      Console.Write("[ ");
      for (int i = bits.Length - 1; i >= 0; --i) {
        Console.Write(bits[i] + " ");
      }
      Console.WriteLine("]");
    }
     
     
       
    December 01

    Gray Code in C#

    Last week I was coding up some Genetic Algorithm programs. In the past I've used mostly C/C++ but this time I wanted to use C#. The first step when implementing GAs is to get your Gray Code routines ready. GAs typically encode information using Gray Code rather than ordinary binary representations. I figured there'd be several sets of C# implementations of Gray Code routines available on the Internet, but a couple hour search yielded only some very weak (and often completely incorrect) sets of code. So, I wrote my own micro-library. One of the big problems is defining exactly what is meant by a Gray Code library. There are many, many variations. Additionally, there is the annoying but not trivial issue of internal representation (where the low-order / least significant bit is stored, and the readable representation (left to right or right to left). In my case, I needed to work with normal C# int types in the range of 0-255 (such as 15), ordinary binary representations of these ints (such as 1111 -- 15 in binary -- in standard readable form), and Gray Code representations (such as 1000 -- 15 in Gray code). In my case I decided to store binary and Gray codes in memory as arrays of 0 and 1 ints. I came up with six convert routines: int to binary, binary to Gray, int to Gray, binary to int, Gray to binary, and Gray to int. For example,
     
    int n = 15;
    int[] binary = IntToBinary(n);  // binary holds [1 1 1 1]
    int[] gray = IntToGray(n);  // gray holds [0 1 1 1]
     
    or
     
    int[] gray = new int[] { 0, 1, 0, 1 };
    int n = GrayToInt(gray);  // n holds 12
     
    I'll post the code in my next blog entry. The moral of the story is that if you are going to work with Gray Code using C#, be prepared to have to spend a couple of hours defining your own custom conversion library.