Checking, if all enum values were processed

Suppose, that there's a piece of code:

enum Directions
{
    North,
    South,
    East,
    West
}

// (...)

switch (dir)
{
    case North : // Do sth
    case South : // Do sth
    case East : // Do sth
    case West : // Do sth
}

Notice especially the lack of default: directive. Now suppose, that later someone added four more values to that enum: NorthEast , NorthWest , SouthEast , SouthWest . In such case it is likely, that the quoted code will effect in undefined behavior, because there is no security measure to handle possible extensions to Directions enumeration type.

I've got some questions regarding this matter.

  • Shall a programmer implement a security measure here, eg:

    default: throw new InvalidArgumentException("Unsupported enum value!");
    
  • Should this matter be tested in unit testing?

    // Naïve implementation, for example purposes only
    [ExpectedException(typeof(InvalidArgumentException))]
    [Test]
    void SomeTestMethod()
    {
        SomeFunction((Direction)-1);
    }
    

    If so, how would you automate such kind of test (eg. find ordinal value different from all other values in this enum, take into consideration enum backing type etc.)?

  • Should this matter be verified during static code analysis? Which tool can provide such informations? I've written simple Proof-of-concept in VS 2012 Pro, run code analysis, but IDE reported, that 'No code analysis issues were detected'.

    The code:

    namespace ManagedConsoleSketchbook
    {
        class Program
        {
            enum MyEnum
            {
                One,
                Two,
                Three
            }
    
            static void Main(string[] args)
            {
                MyEnum e = MyEnum.One;
    
                switch (e)
                {
                    case MyEnum.One:
                        break;
                    case MyEnum.Two:
                        break;
                }
            }
        }
    }
    
  • Is there a generic approach to this general problem? Eg. maybe I can write sophisticated test method in C# using reflection, but in C++ it's a lot harder to nail down such potential code integrity breach than in C# or other higher-level languages.


  • Why do I ask about if it should be checked during unit testing? It's because - as far as I know - unit tests shall verify, if method behaves as it is supposed (documented) to. In this case it is supposed to accept any of four enum elements and it actually do it, so all tests should pass. Checking for potential problems seems to me not to be a concern of the unit testing process. If I'd like to verify all possibilities of potential problems in unit tests, I'd probably end up with writing a hundreds of tests for 3-line-of-code methods.

    On the other hand it seems like a quite cheap (in terms of spent resources) way of making sure, that the method won't cause any serious problems, when someone decides to add another value to an enum.


    1: Yes, I do this routinely.

    2: Yes. I would add this:

    [ExpectedException(typeof(InvalidArgumentException))]
    [Test]
    void SomeTestMethod()
    {
        Direction testValue = (Direction)-1;
        Assert.IsFalse(Enum.IsDefined(typeof(Direction), testValue));
        SomeFunction((Direction)-1);
    }
    

    This problem is actually handled in VS-2012. Note that this test is disabled by default.

    After enabling the warning you can instruct Vs to treat this particular warning as an error.


  • Yes
  • That would be ideally to test.
  • I don't know of a tool that can do it.
  • The easiest way is to ALWAYS have a default clause. When the default should not do anything write something like:

    default:
        // No action required
        break;
    

    This way you the programmer at least thought about the left over items (if there are any).

  • 链接地址: http://www.djcxy.com/p/73382.html

    上一篇: 使用NUnit Assert.Throws方法或ExpectedException属性?

    下一篇: 检查,如果所有的枚举值被处理