Developing Drivers with the Windows Driver Foundation (Pro Developer)

Many annotations are straightforward and obvious to write, but some can take a little effort to get right. PREfast attempts to diagnose any errors it sees in annotations, but it cannot check and report every conceivable error. It is always a good idea to write a small test case to confirm that annotations behave as you expect.

A good test case should report any expected errors and should not report instances of correct usage. Simple annotations such as __in do not benefit from test cases, but annotations that involve sizes-in particular, annotations that use the __part modifier-often benefit from test cases because writing the test cases often forces you to think about corner cases.

Examples of Annotation Test Cases

The example in Listing 23-34 shows a set of very simple test cases for the myfun function, which takes three parameters: mode, p1, and p2. The value of mode determines valid values for p1 and p2, so the test cases use the __drv_when conditional annotation to specify how to enforce correct usage of myfun.

Listing 23-34: Example of annotation test cases for a function

// Annotate the prototype. __drv_when(mode==1, drv_arg(p1, __null)) __drv_when(mode==2, drv_arg(p2, __null)) __drv_when(mode <= 0 || mode > 2, __drv_reportError("bad mode value")) void myfun(__in int mode, __in struct s *p1, __in struct s *p2);

Starting with the first annotation, the prototype establishes the following usage requirements:

In Listing 23-35, the test cases call the function correctly and incorrectly. Incorrect calls cause PREfast to issue a warning.

Listing 23-35: Example of code that exercises annotation test cases

// A correct use void dummy1(__in struct s *a, __in struct s *b) { myfun(0, a, b); } // An incorrect use: expect a warning void dummy2(__in struct s *a, __in struct s *b) { myfun(1, a, b); } // An incorrect use: expect a warning void dummy3(__in struct s *a, __in struct s *b) { myfun(2, a, b); } // A correct use void dummy4(__in struct s *a, __in struct s *b) { myfun(1, NULL, b); } // A correct use void dummy5(__in struct s *a, __in struct s *b) { myfun(2, a, NULL); } // An incorrect use: expect a warning void dummy6(__in struct s *a, __in struct s *b) { myfun(14, a, b); }

Tips for Writing Annotation Test Cases

Consider these tips when writing annotation test cases:

Категории