.+c "Writing New Tests"
.sh 1 "Analysing missed coverage" 1
.lp
Type
.nf
\fH
% greport LOG
\fR
.fi
You should see:
.nf

"lc.c", line 255: operator > might be >=. (L==R)
"lc.c", line 255: condition 1 (argc, 1) was taken TRUE 42, FALSE 0 times.
"lc.c", line 257: condition 1 (<...>[...], 1) was taken TRUE 0, FALSE 14 times.
"lc.c", line 271: if was taken TRUE 0, FALSE 28 times.
"lc.c", line 280: loop zero times: 0, one time: 18, many times: 10.
"lc.c", line 290: if was taken TRUE 0, FALSE 40 times.
"lc.c", line 425: if was taken TRUE 37, FALSE 0 times.
"lc.c", line 860: loop zero times: 0, one time: 5, many times: 19.
"lc.c", line 872: loop zero times: 0, one time: 0, many times: 6.

.fi
You'll notice that this looks a lot like error output from a C compiler.
This is intentional, for two reasons:
.np
Psychological.  As with a compiler's output, you examine the errors
(in this case, test deficiencies), fix them, redo the compile (rerun
the test suite), and repeat the process until you get no more output.
Just as with a compiler, the messages you see may prompt large
changes, larger than is strictly necessary to make them go away.
.np
Practical.  These error messages are compatible with the
\fBerror(1)\fR program (on BSD UNIX) and the GNU Emacs \fHnext-error\fR
function.  (A version of \fHnext-error\fR tailored to GCT is provided with
GCT.  If you're an Emacs user, you may want to look at Appendix A
now.)
.lp
Let's examine the output line by line.  The first two lines of \fBgreport\fR
output refer to line 255, which is the option processing loop.  
The line in question is highlighted below, but I recommend you edit
\fIlc.c\fR; the discussion will be easier to follow if you don't have
to constantly flip pages of this tutorial.
.nf

    \fBwhile (--argc > 0 && (**++argv == '-'))\fR
    {
	if (  (*argv)[1] == LCURL || (*argv)[1] == RCURL)
	{
	    white_bracket = TRUE;
	}
	else if (sscanf (*argv + 1, "%d", &page_size) == FALSE)
	{
	    fprintf (stderr, "lc: Bad page size argument: %s\\n", *argv);
	    exit (BAD_FLAG);			/* Forgive me, Edsger */
	}
    }

.fi
.ne 5
The first \fBgreport\fR line, 
.nf

"lc.c", line 255: operator > might be >=. (L==R)

.fi
is from \fIrelational\fR coverage, which checks for tests that probe
common misuses of relational operators.  In this case, we're worried
that the programmer made the common mistake of using \fH>\fR instead
of the correct \fH>=\fR.  Suppose that happened.  We want to write the test
that will have the best chance of revealing the bug; that is, we want
a test where what the correct program would do is as different as
possible from what the program we have does.
.lp
If \fH--argc\fR is exactly 0, the correct program (\fH--argc>=0\fR)
would enter the body of the \fHwhile\fR loop, while the buggy program
(\fH--argc>0\fR)
won't.  For all other values of \fHargc\fR, the correct and buggy
program will take the same path.  It seems that \fHargc==0\fR, the
boundary condition, is the best test to find this particular bug; GCT
is telling us we never tried it.
.lp
To force this case, the call to \fBlc\fR must have no non-option
arguments.  It must look like one of these:
.nf
\fH
% lc < INPUT
% lc -} < INPUT
% lc -34 < INPUT
\fR
.fi
If you look at the \fBrun-suite\fR file, you'll see that there are no
such tests:  \fBlc\fR is never tested when it takes its input from
standard input.  This is a major omission.  Rather than writing a test
like this right away, we should write down "input from standard input"
as a \fItest condition\fR in a separate list of test conditions.  We
may later be able to combine several of these test conditions into a
single test case, which saves us effort.\**
.(f
\** It's also likely to result in a better test -- more complicated
test cases are better (up to a point) because they are more likely to
catch bugs by chance.
.)f
.lp
The next line of \fBgreport\fR output is from the same line of the
program.
.nf

"lc.c", line 255: condition 1 (argc, 1) was taken TRUE 42, FALSE 0 times.

.fi
This is from \fImulticondition\fR coverage, which checks that all parts of
a logical expression are used.  Line 255's \fHwhile\fR loop test has two
components:
.nf

   \fH--argc > 0\fR

and

   \fH**++argv == '-'\fR

.fi
The first of them was always true in every test, never false.  The
second component isn't mentioned, because it's evaluated to both
true and false.  If you want to see how many times it's evaluated
to each value, use \fBgreport -all\fR (see the manpage).
.lp
This condition tells us the same thing that we already knew.
To get \fHargc\fR equal to zero, there can be only arguments beginning
with a dash -- that is, \fBlc\fR must take its input from standard
input.
.lp
.ne 20
The next line, 
.nf

"lc.c", line 257: condition 1 (<...>[...], 1) was taken TRUE 0, FALSE 14 times.

.fi
corresponds to this code:
.nf

    while (--argc > 0 && (**++argv == '-'))
    {
	\fBif (  (*argv)[1] == LCURL || (*argv)[1] == RCURL)\fR
	{
	    white_bracket = TRUE;
	}
	else if (sscanf (*argv + 1, "%d", &page_size) == FALSE)
	{
	    fprintf (stderr, "lc: Bad page size argument: %s\\n", *argv);
	    exit (BAD_FLAG);			/* Forgive me, Edsger */
	}
    }

.fi
It is also an example of multicondition coverage, but
the message looks peculiar.
What does \fH(<...>[...], 1)\fR mean?  It's there in case "condition 1" is
not enough to locate the condition \fBgreport\fR refers to.
(In this case, the condition is \fH(*argv)[1] == LCURL\fR.)
.lp
Conditions are numbered from left to
right.  But in a deeply nested expression, like (A && (B || C) || D), it can
be hard to count conditions accurately.  The parenthetical remark
helps you find them.  The first component is the leftmost operand of
the condition.  In this case, it's \fH(*argv[1])\fR.  \fBGreport\fR always
abbreviates arrays as \fIarrayname\fR\fH[...]\fR, because the expression in
the array is often complex and would make the line too long.  When
\fIarrayname\fR is more complicated than a simple identifier, GCT
abbreviates it as \fH<...>\fR, again to save space.
.lp
These abbreviation rules are probably a bad idea, but in practice it's
rarely difficult to figure out what subexpression is meant.  As an
additional help, the number in parenthesizes is the nesting depth of
the subexpression, starting with 1.  (It's always deeply parenthesized
expressions that cause trouble.)
.lp
What this line tells us is that \fH*argv[1]\fR is never
\fHLCURL\fR.  That is, we've never given the program the \fH-{\fR option.  A
quick check of \fBrun-suite\fR confirms this.  We'll write that down
in our test condition list.
.lp
The next line,
.nf

"lc.c", line 271: if was taken TRUE 0, FALSE 28 times.

.fi
tells us that this \fHif\fR has never been taken in the true direction.
.nf

    \fBif (argc == 0)\fR
    {
        tally_file (stdin, &file_tally);
        show_header ();
        show_tally ("", &file_tally);
    }

.fi
We already knew that:  the program never reads from standard input.
.ne 5
.lp
.ne 5
The next line, 
.nf

"lc.c", line 280: loop zero times: 0, one time: 18, many times: 10.

.fi
.ne 24
is the first example of \fIloop\fR coverage.  This particular loop
traverses all of \fBlc\fR's non-option arguments.
.nf

	\fBfor (index = 1; index <= argc; index++)\fR
	{
	    if ((fp = fopen (*argv, "r")) == NULL)
	    {
		status = FILE_NOT_FOUND;
		fprintf (stderr, "lc: can't open %s\\n", *argv);
	    }
	    else
	    {
		tally_file (fp, &file_tally);
		if (fclose (fp) == EOF)
		    panic (PANIC, "Fclose error.");
		show_tally (*argv, &file_tally);
		if (argc > 1)
		    make_total (&total_tally, &file_tally);
	    }
	    argv++;
	}

.fi
.lp
A \fBgreport\fR line for a loop tells about three types of traversals:
.np
ones where the loop test failed on the first try, so the loop was
never entered. 
.np
ones where the loop test failed on the second try, so the loop body
was executed exactly once.
.np
ones where the loop was traversed more than once.
.lp
Some types of bugs are only detected by one of these cases (though the
single-traversal case is probably the least useful).  
.lp
In this particular case, we know that \fHargc>0\fR (because we just looked
at the \fHif\fR statement that handled the zero case).  So it is impossible to
traverse the while loop 0 times.  This is an example of an
\fIinfeasible test condition\fR.  We can ignore it.  
.lp
Of the two feasible cases, we see that \fBlc\fR was given a single
argument 18 times and more than one argument 10 times.
.lp
We move on to:
.nf

"lc.c", line 290: if was taken TRUE 0, FALSE 40 times.

.fi
which corresponds to this line:
.nf

                if (fclose (fp) == EOF)
                    panic (PANIC, "Fclose error.");

.fi
Evidently, the programmer thinks an \fHEOF\fR return from
\fHfclose()\fR is impossible (but is checking anyway, just in case).
Of course, what a programmer thinks and what is true may be two
different things.  We as testers would want to think hard about how to
generate \fHEOF\fR returns.  (Error handling is a fertile source of
serious bugs caused by mistaken assumptions.)  Let's assume that we'll
fail, that this is another example of an infeasible test condition.
.ne 5
.lp
.ne 5
This line,
.nf

"lc.c", line 425: if was taken TRUE 37, FALSE 0 times.

.fi
is another sanity check:
.ne 5
.nf

       if (line_info.blank)
           (file_tally->blank)++;
       else
           panic (PANIC, "Non-empty line contains nothing.");

.fi
It's never been taken in the false direction, and the programmer
believes it can't be.  In thorough testing, we'd think hard
about this; for this tutorial, we'll move on.
.lp
.ne 15
The next line,
.nf

"lc.c", line 860: loop zero times: 0, one time: 5, many times: 19.

.fi
is another impossible loop case (these are not uncommon):
.nf

	\fBfor (index = 0; index < 4; index++)\fR
	{
	    c = PULL_OFF(fp);
	    if (c != QUOTE)			/* store it. */
		chars[index] = c;
	    else				/* found what we want. */
		break;
	}

.fi
It is impossible for this loop not to be entered; hence
the "zero times" case in loop coverage can never have a value other
than zero.  (The loop can be entered exactly once, though, if the
\fHbreak\fR statement is executed the first time through.  This happened 5
times.)
.lp
The final line of \fBgreport\fR output is this:
.nf

"lc.c", line 872: loop zero times: 0, one time: 0, many times: 6.

.fi
which corresponds to this code:
.nf

    \fBfor (index = 3; index >= 0; index--)\fR
    {
        c = chars[index];    /* because chars[array] is too big to expand in PUSH_BACK. */
        PUSH_BACK(c, fp);
    }

.fi
This is another impossible while loop.  It always counts down from 3
to 0, so it can never be taken zero or one times.
.lp
We're finished.  We generated only a short list of things to test.
This is as it should be, given a thorough starting test suite.  We
wasted some time looking at impossible conditions, but not very much.
.sh 1 "The new tests"
.lp
We have two new test conditions:
.nf

1. input from standard input.
2. Use the -{ option.

.fi
This is easy to do with a single test, which you should just type to
the shell:
.nf

\fH% echo "{" | lc -\\{\fR

.fi
(The backslash in front of the \fH{\fR is to prevent the shell from
interpreting it specially.)
This is not a very thorough test of the \fH-{\fR option, but it will do for
this tutorial.  Is the output correct?
.lp
Now type 
.nf

\fH% gsummary LOG\fR

.fi
You'll see that total coverage has gone up to 96.65%.  
\fBGreport\fR shows:
.nf

"lc.c", line 280: loop zero times: 0, one time: 18, many times: 10.
"lc.c", line 290: if was taken TRUE 0, FALSE 40 times.
"lc.c", line 425: if was taken TRUE 38, FALSE 0 times.
"lc.c", line 860: loop zero times: 0, one time: 5, many times: 19.
"lc.c", line 872: loop zero times: 0, one time: 0, many times: 6.

.fi
We know that all of these are infeasible.
.sh 1 "Suppressing infeasible coverage"
.lp
It's annoying that we can't make the infeasible test conditions go
away.  Worse, if we're testing a large program - one where it may take
us several tries to eliminate all feasible test conditions - we don't
want to waste time looking at infeasible conditions every time we run
\fBgreport\fR after a change to the test suite.
.lp
The \fBgedit\fR program can help.  To use it, type
.nf

\fH% greport -edit LOG > edit.g\fR

.fi
Edit \fIedit.g\fR.  You'll see this:
.nf

"lc.c", line 280: [25: 0 0 18 10] loop zero times: 0, one time: 18, many times: 10.
"lc.c", line 290: [34: 0 40] if was taken TRUE 0, FALSE 40 times.
"lc.c", line 425: [75: 38 0] if was taken TRUE 38, FALSE 0 times.
"lc.c", line 860: [167: 0 0 5 19] loop zero times: 0, one time: 5, many times: 19.
"lc.c", line 872: [180: 0 0 0 6] loop zero times: 0, one time: 0, many times: 6.

.fi
The numbers in brackets are the raw versions of what the text says.
In the first case (line 280), the first 0 is the number of times the
loop was skipped.  The next two numbers (0 and 18) add up to the
number of times the loop was entered exactly once.  (The reason why
there are two numbers is unimportant - it's due to the implementation
of loop coverage.)  The final number (10) is the number of times the
loop was traversed many times.
In the case of branches, like line 290, the first number is the true count, the
second the false count.
.lp
Replace the zeros that are impossible with either "s", "S", "0s", or "0S":\**
.(f
\** If you're using Emacs "gedit-mode", SPC will helpfully position
you at the first zero in the next line.
.)f
.nf

"lc.c", line 280: [25: \fB0S\fR 0 18 10] loop zero times: 0, one time: 18, many times: 10.
"lc.c", line 290: [34: \fBS\fR 40] if was taken TRUE 0, FALSE 40 times.
"lc.c", line 425: [75: 38 \fBS\fR] if was taken TRUE 38, FALSE 0 times.
"lc.c", line 860: [167: \fBS\fR 0 5 19] loop zero times: 0, one time: 5, many times: 19.
"lc.c", line 872: [180: \fBS 0S\fR 0 6] loop zero times: 0, one time: 0, many times: 6.

.fi
.ne 8
Notice that you only had to replace one of the zeroes in the "single
traversal" case of the last loop.
.lp
Now type 
.nf
\fH
% gedit edit.g
% gsummary LOG\fR

.ne 30
.sp
You'll see:

BINARY BRANCH INSTRUMENTATION (76 conditions total)
0 ( 0.00%) not satisfied.
76 (100.00%) fully satisfied. [2 ( 2.63%) suppressed]

SWITCH INSTRUMENTATION (14 conditions total)
0 ( 0.00%) not satisfied.
14 (100.00%) fully satisfied.

LOOP INSTRUMENTATION (24 conditions total)
0 ( 0.00%) not satisfied.
24 (100.00%) fully satisfied. [4 (16.67%) suppressed]

MULTIPLE CONDITION INSTRUMENTATION (38 conditions total)
0 ( 0.00%) not satisfied.
38 (100.00%) fully satisfied.

OPERATOR INSTRUMENTATION (27 conditions total)
0 ( 0.00%) not satisfied.
27 (100.00%) fully satisfied.

SUMMARY OF ALL CONDITION TYPES (179 total)
0 ( 0.00%) not satisfied.
179 (100.00%) fully satisfied. [6 ( 3.35%) suppressed]

.fi
If you use \fBgreport\fR, it will show you nothing.  You're done using
coverage on your test suite.

