/* MAXAB: return the maximum of two integers CODE: Here is simple code to find the maximum of a and b: if (a>b) // 1 branch point max = a; // 2 assignment else max = b; // 3 assignment // 4 is just the joining of the two branches 1. FLOWGRAPH: The code has two paths but note that the artificial edge has been added: R1 enter artificial 1 . . . . . . . F | T . +-------+-------+ . | | . v v . R2 . 3 2 . . | | . +-----> 4 <-----+ R3 . exit . . . . . . . . . 2. CYCLOMETRIC COMPLEXITY: All three formulas for CC yield the same result: 2 Predicates (1) + 1 = Edges (5) - Nodes (4) + 1 = Regions (3) - 1 = 2 Now, we want to establish PATH COVERAGE using LINEARLY INDEPENDENT PATHS. The CC tells us that there are two such paths. Given the simple code above, the two paths are go LEFT or go RIGHT: 1. 1-3-4 2. 1-2-4 3. BASIS SET OF CYCLES: This is a mathematical concept. A CYCLE in a graph: 1. starts at a node 2. ends at the same node 3. never touches any other node more than once In our example, we have exactly two BASIS CYCLES (always the same number as CC, and INDEPENDENT PATHS): 1. 1-3-4-1 // start at the top, go LEFT, return to the top via ARTIFICIAL edge 2. 1-2-4-1 // start at the top, go RIGHT, return to the top via ARTIFICIAL edge The code does NOT actually move along the artificial edge, it is just graph theory. The CYCLES look like the INDEPENDENT PATHS, but that will not be the case with loops in the code. The word "INDEPENDENT" and "BASIS" both mean that the same thing. The PATH (or CYCLE) is not a combination of another PATH (or CYCLE). You'll see the math for this in a later example (avg.c). Obviously, the PATHS (or CYCLES) above definitely look unique. TEST CASES: We need to establish inputs (a and b) and determine the expected result (max) for each of the PATHS: a b max -------------- 1 2 2 // go LEFT: 1-3-4 2 1 2 // go RIGHT: 1-2-4 So, formally, we would do: 4. LINEARLY INDEPENDENT PATHS 5. FEASABLE (YES/NO) 6. TEST CASES 7. RESULT (a,b) (max) 1. 1-3-4 YES 1 2 2 2. 1-2-4 YES 2 1 2 AUTOMATED TEST: See maxab.bat for a Unix script that runs these two test cases INSTRUMENTATION: The actual code below shows the function has "debug", using the helper function L(i). As the code executes, L(i) prints out the current line number, i. */ #include int debug = 0; // global variable that turns ON or OFF the debug /* instrumentation for the line #'s*/ int L(int i) { // given line # i as a parameter if (debug) printf("%d-",i); // if the debug flag is ON, then print the line # return 1; // always return TRUE so L(i) can be used in an IF // statement without harm } int maxab(int a, int b) { // perform white box test on maxab(a,b) int max; // local variable to return if (L(1)&&(a>b)) { // call L(1) to print line #, not part of real logic L(2); max = a; // display line # 2 if the logic goes RIGHT } else { L(3); max = b; // display line # 3 if the logic goes LEFT } L(4); // line # 4 is just the join between the two directions if (debug) // more debug to show the behavior printf("\nActual : max=%d\n",max); return max; // the return value of the maxab function } int main(int argc, char *argv[]) { int a, b; if (argc > 1) { // if ANY argument to program (e.g. -debug) debug = 1; // then turn ON the global flag printf("Path : "); // and start off the instrumentation } scanf("%d %d",&a,&b); // read a and b from input printf("Maximum:%d\n",maxab(a,b)); // display the result }