Brcov Predefined Probe
Contents
Branch Coverage Predefined Probe: brcov.ual
NOTE: This predefined probe is still under development and not all features and platforms are supported.
The brcov.ual predefined probe supports branch coverage analysis on user applications. Branch coverage tells you exactly which branches within a function were actually hit during program execution. This allows you to develop unit test cases which can be used to confirm that all the branches of code you have written are executed and taken.
While this probe is a unique and powerful tool for collecting branch coverage information, it is only a tool. Getting complete branch coverage on a function can be a difficult task, and requires the user to compose test cases which will cause all paths to be executed, including error conditions and exception propagation. The brcov.ual probe can be used with the coverage.ual to produce comprehensive test coverage information.
But it should be noted that it is in testing these tricky cases that Aprobe can especially useful, since you as a user can write a probe that modifies the data on_entry to a function to force a specific path through the function, without worrying about how to get the normal caller of that function to pass that erroneous data.
You can find an example that works through some of the issues that arise from using Aprobe to do this in the $APROBE/examples/learn/branch_coverage
directory. Additionally you are encouraged to contact OC Systems to discuss using Aprobe on your specific application.
Usage
This probe is applied at run time using aprobe as described under Branch Coverage UAL Parameters below. The only functions for which data will be collected are functions selected in the configuration file (see Branch Coverage Configuration File). Selecting a function means that branches in the function will be instrumented. Conversely, branches in functions that are not selected will not be instrumented, and no record will be kept of invocations of these functions or branches.
The instrumentation of branches requires that there be accurate source line debugging information recorded in the executable. This generally means that the application or library containing the covered functions:
- must have been compiled with the appropriate debug flag (-g);
- should have been compiled without optimization; and
- must have the debug information still available.
A snapshot of the current state of collected branch coverage data may be written to the APD file while the program is running (see Configuration of Snapshots). Taking such periodic snapshots at known events, like the entry to or exit from a particular function, may help correlate state data with the execution path recorded by the brcov probe. A final snapshot occurs automatically at program termination.
After the application program terminates, the apformat command must be run to produce an XML branch coverage .brc file from the collected data. Use the abrmerge tool to produce reports and from the .brc files. Data from multiple runs may be merged into a single .brc file and a single report using Abrmerge (see abrcmerge below). Coverage data from brcov.ual and coverage.ual can be combined using Abrmerge to produce very extensive reports.
The report produced by the abrcmerge consists of several parts: the "Overall Summary," the "Subprogram Summary," the "Subprogram Details," and the "Source Annotation." (A subprogram is another name for a function, procedure, subroutine -- any callable entity.) The summaries lists the total lines and branches in the subprogram, how many lines/branches were not instrumented nor executed, and the percentage of instrumented lines/branches that were executed for the subprogram. The details section reports whether the subprogram was called, and if it was, it will report how many of the instrumented lines/branches were executed. In cases where coverage is less than 100% for a particular subprogram, the Details section will also list instrumented lines/branches which were not executed. The source section will annotate any provided source files with branch/line coverage information which will assist with test case creation. Some parts of the report are options. The coverage report will look similar to that in Branch Coverage Summary Report.
Branch Coverage UAL Parameters
brcov.ual is specified on the aprobe command line or in an APO file, and with apformat. The specific options are:
aprobe -u brcov[.ual] [-p " [-c config_filename] [-h] [-v]" your_program
For example:
aprobe -u brcov -p "-c foo1.brcov.cfg" foo.exe aprobe -u brcov -p
where:
- -c config_filename
specifies that the name of the probe configuration options file will follow immediately after -c. The default file name is your_program.brcov.cfg. For example, if your executable program is called wilbur.exe, then the default file name would be wilbur.exe.brcov.cfg.- -h
- produces brief help text.
- -v
- verbose mode, which produces additional progress messages.
Note that if you use no UAL parameters, you need not specify UAL names at all. For example:
apformat progname
will format progname.apd
with all the UALs with which it was created.
Branch Coverage Configuration File
The Branch Coverage configuration file is used to specify what subprograms are to be analyzed, when snapshots are to be taken, and other options, as described in Configuration File. The example below shows one possible Branch Coverage configuration file.
PROBE CONFIGURATION FILE FOR BRCOV VERSION 1.0.0 CoverageEnabledInitially TRUE // Here we select which subprograms we want to cover: COVERAGE "main" COVERAGE extern:"YET_ANOTHER_LOCAL_PROC" COVERAGE "STILL_ANOTHER_LOCAL_PROC" // Here we define which subprogram invocations cause snapshots // to be saved. SNAPSHOT "printf" IN "libc.a(shr.o)" ON ENTRY IS "printf called"
Example D-2. brcov.cfg File
Note that if you do not provide a configuration file, the probe will create a default configuration file for you. This is a good way to get started.
Configuration Variables
The following are the only valid keywords that identify lines to set configuration variables. Each such line must begin with one of these keywords, and the keyword must be followed by a value. Nothing else is allowed on the same line.
CoverageEnabledInitially
This must be followed by the value TRUE or FALSE. The default is TRUE which indicates that data logging will begin as soon as the application program starts running. If set to FALSE, data logging will begin only after a call is made to the probe's function ap_Brcov_Enable(), rather than as soon as the application program starts running.
ShowAllSnapshots
This must be followed by TRUE or FALSE. The default is FALSE. When FALSE, the data from all intermediate snapshots are rolled into the one final report. When TRUE the data for every snapshot will be reported in separate summaries.
ResetSnapshotCounts
This must be followed by TRUE or FALSE. The default is FALSE. When FALSE, the data from all intermediate snapshots accumulate into the one final report. When TRUE the counts are reset for each separate snapshot.
ShowUnconditionalBranches
This must be followed by TRUE or FALSE. The default is FALSE, which indicates that unconditional branches will not be tracked. In general, conditional branches are more interesting than unconditional branches.
Configuration of Branch Coverage Functions
Each function for which branch coverage data is to be collected must be specified explicitly using the COVERAGE, COVERFILE, or COVERUNIT keywords.
The COVERAGE keyword is followed by the name of the function, as described in Configuration of Selected Functions. This directive selects specific functions by name (with possible wildcards).
The COVERFILE keyword is followed by the name of a file and an option module name. This keyword selects the functions originating from the designated source file (with possible wildcards).
The COVERUNIT keyword is followed by the name of a PowerAda unit. This keyword selects the functions originating from the designated PowerAda unit (with possible wildcards).
By default, if no COVERAGE/COVERFILE/COVERUNIT lines exist, then coverage data will only be collected for the "main()" function of the application module.
The REMOVE keyword allows you to specify subprograms that should not be instrumented for logging coverage data. This is useful when used in conjunction with a wildcard ("*"), to gather data about everything except certain routines.
Note: COVERAGE "*"
is not a particuarly useful concept since it is important for you to identify and isolate your functions carefully in order to use test coverage for its intended purpose.
Configuration of Snapshots
The branch coverage probe configuration file allows you to specify the name of some subprograms for which snapshots of the coverage data are to be automatically taken. This is done with lines beginning with the keyword SNAPSHOT.
Each SNAPSHOT line must specify a particular subprogram in the usual manner, just as is done for a COVERAGE line.
The remainder of the SNAPSHOT line contains pairs, where each pair has a special identifier keyword followed by its own associated value. These pairs give supplementary information about the snapshot.
- ON - This optional special identifier must be followed by the value ENTRY or EXIT, to denote that the snapshot is to be taken on entry to or exit from the subprogram respectively.
- IS - This optional special identifier must be followed by an (arbitrarily long) string enclosed within quotation marks (""). It specifies a textual description or title that is to be logged along with the snapshot.
Test Coverage API
Users can control the behavior of the coverage probe by calls from within their own probes. The API for the trace probe is defined by [../include/coverage.h $APROBE/include/brcov.h
]. Some of the functions exported by brcov.ual are:
- ap_Brcov_Enable - Enables logging of coverage data.
- ap_Brcov_Disable - Disables logging of coverage data.
- ap_Brcov_DoSnapshot - Dumps current coverage information.
See Snapshots for more information and an example.
Branch Coverage Performance Issues
See Performance Issues for a general discussion of factors that affect performance.
The branch coverage probe is applied to the functions specified in the configuration file, so the run-time overhead is directly proportional to the number of calls to the functions selected and the number of branches executed in each function. The branch coverage probe simply increments an integer for each branch executed, so the amount of data is a constant multiple of the number of branches being covered, though additional snapshots increase this.
As branch coverage analysis is generally a unit-testing activity, it is mostly done on the small number of related functions under test, so performance should not be an issue. Application-wide branch coverage analysis during integration testing is not recommended.
Abrmerge
The results of multiple runs of brcov.ual (and coverage.ual) over the same executable may be merged into a single "combined summary" report using abrmerge.
A merged summary report is useful when running many tests, each with different input data or perhaps different probes, to force all logic paths to be executed. abrmerge can also merge branch data files to accumulate data from multiple runs into a single file.
A simple example
This example of the brcov.ual (and coverage.ual) predefined probe can be found in $APROBE/examples/predefined_probes/brcov
.
The test application is very simple. It just prints out a mini-menu and waits for you to select 1 or 2. Depending on your selection, it does one of two actions. You can see this in the DoProcessing() function in coverage_example.c. We want to exercise every branch in this function -- we refer to this as getting 100% coverage.
Note that, unlike some other uses of Aprobe, branch and line coverage requires you to be familiar with (the lines in) your source code to make most effective use of the probe.
As before, we'll use make to build the example application:
cd $APROBE/examples/predefined_probes/brcov make aprobe -u brcov -u coverage coverage_example
When the example application prompts you for a choice, enter the number 1. That will print out the first string and then the application will exit normally.
As before, aprobe stored the data in .apd files, so use apformat to format it:
apformat coverage_example
and abrmerge to merge and view it:
abrmerge *.brc *.c
Here's a portion of the report showing the line and branch coverage we've achieved:
coverage_example.c: Line Br O/I/T/N Line Cnt Source ------ ----------- --------- ------- - - 1 : : : /* This is a simple example to demonstrate using coverage.ual */ 2 : : : #include <stdio.h> 3 : : : #include <stdlib.h> 4 : : : 5 : : : /* This is the function we are interested in. */ 6 : : : void DoProcessing (void) 7 : : 1 : { 8 : : 1 : int Option = 0; 9 : : : char Buffer [100]; 10 : : : 11 : : 1 : printf ("1. Print string #1\n"); 12 : : 1 : printf ("2. Print string #2\n"); 13 : : : + 14 : 2/2/1/2 : 2 : while (Option < 1 || Option > 2) 1 -> 16 0 -> 16 15 : : : { 16 : : 1 : printf (" Enter your choice (1 or 2): \n"); 17 : : 1 : fgets (Buffer, 99, stdin); 18 : : 1 : Option = atoi (Buffer); 19 : : : } 20 : : : + 21 : 2/2/1/0 : 1 : switch (Option) 1 -> 24 0 -> 28 22 : : : { 23 : : : case 1: 24 : : 1 : printf ("This is string #1 - pretty exciting, huh?!\n"); 25 : : 1 : break; 26 : : : 27 : : : case 2: * 28 : : 0 : printf ("This is string #2 - it doesn't get any better than this!\n"); * 29 : : 0 : break; 30 : : : } 31 : : 1 : } 32 : : : 33 : : : int main (int argc, char **argv) 34 : : 1 : { 35 : : 1 : DoProcessing (); 36 : : 1 : return 0; 37 : : 1 : } O - Number of offsets for line B - Number of branches for line I - Number of offsets/branches instrumented I% - Percentage of offsets/branches instrumented H - Number of offsets/branches hit H% - Percentage of offsets/branches hit T - Number of branches taken N - Number of branches not taken + - Partial coverage on this line * - No coverage on this line
Using abrmerge
Sometimes we want to combine several test and branch coverage reports into a single report. Use abrmerge to accomplish this.
The above 2 lines that were not executed are specific to choice number 2. We could easily execute the lines of choice number 2 if we ran it again, but then we wouldn't be able to cover the choice 1 lines. If you look in the local directory, you'll see a coverage_example.tc file. This was created at format time by the coverage predefined probe and is a binary representation of the above data. It contains the coverage data obtained during choice 1, so let's save it.
We typically use abrmerge to merge results from many .brc files (perhaps .brc files produced by coverage.ual and brcov.ual) and display the combined data, but it can also act on just one file. We need to save the current .brc file, and copying it would do, but we'll use abrmerge to demonstrate it a little:
abrmerge -m combined.brc brcov_example.brc
This "merges" the data in the input .brc files (only brcov_example.brc) and outputs it in combined.brc (which, in this case, means that combined.brc ends up with the same data). You can verify that this combined.brc file has the same data by just running abrmerge on it:
abrmerge combined.brc
Now run the application again using aprobe:
aprobe -u brcov brcov_example
Select choice 2, then after the application ends re-run apformat:
apformat brcov_example
This time we get a different set of lines executed, as expected. Use the abrmerge command to combine the data in combined.brc (from the first run) with the data from this run (in a new brcov_example.brc):
abrmerge -m combined.brc brcov_example.brc combined.brc
Now we get the 100% coverage we wanted!
The on-line example in $APROBE/examples/learn/branch_coverage
extends this by illustrating how to use your own probes in combination with coverage.ual to ensure all lines are executed.
Branch Coverage Report
The final output of the learn/branch_coverage
example looks like this:
Aprobe Coverage Summary Report Generated: 12 May 2017 13:36:25 -0400 -------------------------------------------------------------------------- Contents -------------------------------------------------------------------------- TimeStamps Overall Summary Function TOC File TOC Function Summaries Function Details File Coverage -------------------------------------------------------------------------- Timestmaps -------------------------------------------------------------------------- TimeStamp: Program : /home/swn/aprobe/test/brcov/i2419e/brtestc.exe Host : centos7 PID : 18865 Start Time: 2017-05-11 17:41:53 End Time : 2017-05-11 17:57:58 -------------------------------------------------------------------------- Overall Summary -------------------------------------------------------------------------- Lines Lines Line Branches Branches Branches Branch Total Total Not Not Coverage Total Not Not Branches Not Coverage Calls Lines Probed Executed Percent Branches Probed Executed Taken Taken Percent Name ------- ------- -------- --------- --------- --------- --------- ---------- --------- --------- -------- --------- - - -1 -1 -1 -1 0 0 0 0 0 0 0 "crtstuff.c":"__do_global_dtors_aux()" -1 -1 -1 -1 0 0 0 0 0 0 0 "crtstuff.c":"deregister_tm_clones()" -1 -1 -1 -1 0 0 0 0 0 0 0 "crtstuff.c":"frame_dummy()" -1 -1 -1 -1 0 0 0 0 0 0 0 "crtstuff.c":"register_tm_clones()" 381878 14 0 1 92 3 0 0 3 3 100 extern:"ExprFunc()" 381878 182 0 28 84 70 0 12 19 39 82 extern:"IfFunc()" 381878 27 0 5 81 5 0 0 3 5 100 extern:"LoopFunc()" 381878 21 0 1 95 2 0 0 2 2 100 extern:"LoopSwitchFunc()" 381878 5 0 1 80 0 0 0 0 0 0 extern:"StraightLineFunc()" 381878 17 0 1 94 1 0 0 1 1 100 extern:"SwitchFunc()" -1 -1 -1 -1 0 0 0 0 0 0 0 extern:"__libc_csu_fini()" -1 -1 -1 -1 0 0 0 0 0 0 0 extern:"__libc_csu_init()" -1 -1 -1 -1 0 0 0 0 0 0 0 extern:"__x86.get_pc_thunk.bx()" -1 -1 -1 -1 0 0 0 0 0 0 0 extern:"_fini()" -1 -1 -1 -1 0 0 0 0 0 0 0 extern:"_init()" -1 -1 -1 -1 0 0 0 0 0 0 0 extern:"_start()" -1 -1 -1 -1 0 0 0 0 0 0 0 extern:"ident()" -1 -1 -1 -1 0 0 0 0 0 0 0 extern:"main()" Note: Negative counts indicate the function/line was not instrumented. Funcs Func Lines Lines Lines Branches Branches Branches Branch Total Not Coverage Total Not Not Coverage Total Not Not Branches Not Coverage Funcs Called Percent Lines Probed Executed Percent Branches Probed Executed Taken Taken Percent -------- -------- -------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- 18 12 33 266 0 37 86 81 0 12 28 50 85 -------------------------------------------------------------------------- Function TOC -------------------------------------------------------------------------- "crtstuff.c":"__do_global_dtors_aux()" (<>) "crtstuff.c":"deregister_tm_clones()" (<>) "crtstuff.c":"frame_dummy()" (<>) "crtstuff.c":"register_tm_clones()" (<>) extern:"ExprFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) extern:"IfFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) extern:"LoopFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) extern:"LoopSwitchFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) extern:"StraightLineFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) extern:"SwitchFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) extern:"__libc_csu_fini()" (<>) extern:"__libc_csu_init()" (<>) extern:"__x86.get_pc_thunk.bx()" (<>) extern:"_fini()" (<>) extern:"_init()" (<>) extern:"_start()" (<>) extern:"ident()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) extern:"main()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) -------------------------------------------------------------------------- Files TOC -------------------------------------------------------------------------- brtestc.c -------------------------------------------------------------------------- Function Coverage Summaries -------------------------------------------------------------------------- "crtstuff.c":"__do_global_dtors_aux()" (<>) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 "crtstuff.c":"deregister_tm_clones()" (<>) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 "crtstuff.c":"frame_dummy()" (<>) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 "crtstuff.c":"register_tm_clones()" (<>) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 extern:"ExprFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) Calls: 381878 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: 14 14 0 13 Percent: 100 0 92 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 3 3 3 3 3 Percent: 100 100 100 100 extern:"IfFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) Calls: 381878 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: 182 182 0 154 Percent: 100 0 84 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 70 70 58 19 39 Percent: 100 82 27 55 extern:"LoopFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) Calls: 381878 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: 27 27 0 22 Percent: 100 0 81 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 5 5 5 3 5 Percent: 100 100 60 100 extern:"LoopSwitchFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) Calls: 381878 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: 21 21 0 20 Percent: 100 0 95 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 2 2 2 2 2 Percent: 100 100 100 100 extern:"StraightLineFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) Calls: 381878 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: 5 5 0 4 Percent: 100 0 80 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 extern:"SwitchFunc()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) Calls: 381878 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: 17 17 0 16 Percent: 100 0 94 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 1 1 1 1 1 Percent: 100 100 100 100 extern:"__libc_csu_fini()" (<>) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 extern:"__libc_csu_init()" (<>) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 extern:"__x86.get_pc_thunk.bx()" (<>) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 extern:"_fini()" (<>) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 extern:"_init()" (<>) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 extern:"_start()" (<>) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 extern:"ident()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 extern:"main()" (/home/swn/aprobe/test/brcov/i2419e/brtestc.c) Calls: -1 Lines Probed Not Probed Hit ------- -------- ---------- ---------- Count: -1 0 -1 0 Percent: 0 0 0 Branches Probed Hit Taken NotTaken ---------- ---------- ---------- ---------- ---------- Count: 0 0 0 0 0 Percent: 0 0 0 0 -------------------------------------------------------------------------- File Coverage -------------------------------------------------------------------------- brtestc.c: Line Branch Line Count Count Source ------ ------- ------- ------ - - 1 : 2 : #include <stdlib.h> 3 : 4 : int ident(int i) 5 : { 6 : return i; 7 : } 8 : 9 : int StraightLineFunc(int i) 10 381878 0 : { 11 381878 0 : int result = 0; 12 : 13 381878 0 : result = result + i; 14 381878 0 : return result; * 15 0 0 : } 16 : 17 : int LoopFunc(int i) 18 381878 0 : { 19 381878 0 : int j = 0; 20 381878 0 : int k = 0; 21 : 22 : /* no iterations */ + 23 381878 1 : for (j = 0; j < 0; j++) 0 -> 25 24 : { * 25 0 0 : k = k + i; 26 : } 27 : 28 4200658 1 : for (j = 0; j < 10; j++) 3818780 -> 30 29 : { 30 3818780 0 : k = k + i; 31 : } 32 : 33 381878 0 : j = 0; + 34 381878 1 : while (j < 0) 0 -> 36 35 : { * 36 0 0 : k = k + 2; * 37 0 0 : j = j + 1; 38 : } 39 : 40 381878 0 : j = 0; 41 4200658 1 : while (j < 10) 3818780 -> 43 42 : { 43 3818780 0 : k = k + 2; 44 3818780 0 : j = j + 1; 45 : } 46 : 47 381878 0 : j = 0; 48 : do 49 : { 50 3818780 0 : k = k + 2; 51 3818780 0 : j = j + 1; 52 : } 53 3818780 1 : while (j < 10); 3436902 -> 50 54 : 55 381878 0 : return k; * 56 0 0 : } 57 : 58 : 59 : int ExprFunc(int i) 60 381878 0 : { 61 381878 0 : int k = 0; 62 : 63 381878 1 : k = (i > 2 ? 5 : 1); 3 -> 63 64 : 65 381878 2 : k = (i > 5 ? (i < 10 ? 5 : 1) : 7); 6 -> 65 381867 -> 65 66 : 67 381877 0 : return k; * 68 0 0 : } 69 : 70 : 71 : int SwitchFunc(int i) 72 381878 0 : { 73 381878 0 : int k = 0; 74 : 75 381878 1 : switch (i) 381872 -> 95 76 : { 77 : case 0: 78 1 0 : k = k + 1; 79 1 0 : break; 80 : case 1: 81 1 0 : k = k + 1; 82 1 0 : break; 83 : case 2: 84 1 0 : k = k + 2; 85 : case 3: 86 2 0 : k = k + 3; 87 2 0 : break; 88 : case 4: 89 1 0 : k = k + 4; 90 1 0 : break; 91 : case 5: 92 1 0 : k = k + 5; 93 1 0 : break; 94 : default: 95 381872 0 : k = k + 6; 96 : } 97 : 98 381878 0 : return k; * 99 0 0 : } 100 : 101 : 102 : int LoopSwitchFunc(int i) 103 381878 0 : { 104 381878 0 : int k = 0; 105 381878 0 : int j = 0; 106 : 107 4200658 1 : for (j = 0; j < 10; j++) 3818780 -> 109 108 : { 109 3818780 1 : switch (i) 3818720 -> 129 110 : { 111 : case 0: 112 10 0 : k = k + 1; 113 10 0 : break; 114 : case 1: 115 10 0 : k = k + 1; 116 10 0 : break; 117 : case 2: 118 10 0 : k = k + 2; 119 : case 3: 120 20 0 : k = k + 3; 121 20 0 : break; 122 : case 4: 123 10 0 : k = k + 4; 124 10 0 : break; 125 : case 5: 126 10 0 : k = k + 5; 127 10 0 : break; 128 : default: 129 3818720 0 : k = k + 6; 130 : } 131 : } 132 : 133 381878 0 : return k; * 134 0 0 : } 135 : 136 : int IfFunc(int i) 137 381878 0 : { 138 381878 0 : int j = 0; 139 381878 0 : int k = 0; 140 : 141 : /* never taken */ + 142 381878 1 : if (ident(j) < 0) 381878 -> 147 143 : { * 144 0 0 : j = j + 1; 145 : } 146 : + 147 381878 1 : if (ident(j) < 1000) 0 -> 153 148 : { 149 381878 0 : j = j + 1; 150 : } 151 : 152 : /* else taken */ + 153 381878 1 : if (ident(j) < 0) 381878 -> 159 154 : { * 155 0 0 : j = j + 1; 156 : } 157 : else 158 : { 159 381878 0 : j = j + 2; 160 : } 161 : 162 : /* second branch */ + 163 381878 1 : if (ident(j) < 0) 381878 -> 167 164 : { * 165 0 0 : j = j + 1; 166 : } + 167 381878 1 : else if (ident(j) < 5) 0 -> 173 168 : { 169 381878 0 : j = j + 2; 170 : } 171 : else 172 : { * 173 0 0 : j = j + 2; 174 : } 175 : 176 : /* multiple conditions */ 177 : + 178 381878 1 : if ((ident(k) < 0) | (ident(j) >= 0)) 0 -> 183 179 : { 180 381878 0 : j = j + 1; 181 : } 182 : + 183 381878 1 : if ((ident(j) >= 0) | (ident(k) == 0)) 0 -> 189 184 : { 185 381878 0 : j = j + 1; 186 : } 187 : 188 : /* all false */ + 189 381878 1 : if ((ident(j) >= 1111110) | 381878 -> 198 190 381878 0 : (1111110 == ident(k)) | 191 381878 0 : (ident(k) == 1111110) | 192 381878 0 : (111110 <= ident(j))) 193 : { * 194 0 0 : j = j + 1; 195 : } 196 : 197 : /* fourth true */ + 198 381878 1 : if ((ident(j) >= 1111110) | 0 -> 207 199 381878 0 : (1111110 == ident(k)) | 200 381878 0 : (ident(k) == 1111110) | 201 381878 0 : (0 <= ident(j))) 202 : { 203 381878 0 : j = j + 1; 204 : } 205 : 206 : /* third true */ + 207 381878 1 : if ((ident(j) >= 1111110) | 0 -> 216 208 381878 0 : (1111110 == ident(k)) | 209 381878 0 : (ident(k) == 0) | 210 381878 0 : (111110 <= ident(j))) 211 : { 212 381878 0 : j = j + 1; 213 : } 214 : 215 : /* second true */ + 216 381878 1 : if ((ident(j) >= 1111110) | 0 -> 225 217 381878 0 : (0 == ident(k)) | 218 381878 0 : (ident(k) == 1111110) | 219 381878 0 : (111110 <= ident(j))) 220 : { 221 381878 0 : j = j + 1; 222 : } 223 : 224 : /* first true */ + 225 381878 1 : if ((ident(j) >= 0) | 0 -> 233 226 381878 0 : (1111110 == ident(k)) | 227 381878 0 : (ident(k) == 1111110) | 228 381878 0 : (111110 <= ident(j))) 229 : { 230 381878 0 : j = j + 1; 231 : } 232 : + 233 381878 1 : if ((ident(j) < 0) & (ident(k) == 0)) 381878 -> 238 234 : { * 235 0 0 : j = j + 1; 236 : } 237 : + 238 381878 1 : if ((ident(j) >= 0) & (ident(k) != 0)) 381878 -> 243 239 : { * 240 0 0 : j = j + 1; 241 : } 242 : + 243 381878 1 : if ((ident(j) >= 0) & (ident(k) == 0)) 0 -> 249 244 : { 245 381878 0 : j = j + 1; 246 : } 247 : 248 : /* all true */ + 249 381878 1 : if ((ident(j) >= 0) & 0 -> 258 250 381878 0 : (ident(k) == 0) & 251 381878 0 : (0 == ident(k)) & 252 381878 0 : (0 <= ident(j))) 253 : { 254 381878 0 : j = j + 1; 255 : } 256 : 257 : /* fourth false */ + 258 381878 1 : if ((ident(j) >= 0) & 381878 -> 267 259 381878 0 : (ident(ident(k)) == 0) & 260 381878 0 : (0 == ident(ident(k))) & 261 381878 0 : (10000 <= ident(j))) 262 : { * 263 0 0 : j = j + 1; 264 : } 265 : 266 : /* third false */ + 267 381878 1 : if ((ident(j) >= 0) & 381878 -> 276 268 381878 0 : (ident(ident(k)) == 0) & 269 381878 0 : (5555 == ident(ident(k))) & 270 381878 0 : (0 <= ident(j))) 271 : { * 272 0 0 : j = j + 1; 273 : } 274 : 275 : /* second false */ + 276 381878 1 : if ((ident(j) >= 0) & 0 -> 285 277 381878 0 : (ident(ident(k)) == 0) & 278 381878 0 : (0 == ident(ident(k))) & 279 381878 0 : (0 <= ident(j))) 280 : { 281 381878 0 : j = j + 1; 282 : } 283 : 284 : /* first false */ + 285 381878 1 : if ((ident(j) >= 10000) & 381878 -> 295 286 381878 0 : (ident(ident(k)) == 0) & 287 381878 0 : (0 == ident(ident(k))) & 288 381878 0 : (0 <= ident(j))) 289 : { * 290 0 0 : j = j + 1; 291 : } 292 : 293 : /* short circuits */ 294 : + 295 381878 2 : if ((ident(k) < 0) || (ident(j) >= 0)) 0 -> 297 0 -> 300 296 : { 297 381878 0 : j = j + 1; 298 : } 299 : + 300 381878 1 : if ((ident(j) >= 0) || (ident(k) == 0)) 381878 -> 302 0 -> 306 301 : { 302 381878 0 : j = j + 1; 303 : } 304 : 305 : /* all false */ + 306 381878 1 : if ((ident(j) >= 1111110) || 0 -> 311 + 307 381878 1 : (1111110 == ident(k)) || 0 -> 311 + 308 381878 1 : (ident(k) == 1111110) || 0 -> 311 + 309 381878 1 : (111110 <= ident(j))) 381878 -> 315 310 : { * 311 0 0 : j = j + 1; 312 : } 313 : 314 : /* fourth true */ + 315 381878 1 : if ((ident(j) >= 1111110) || 0 -> 320 + 316 381878 1 : (1111110 == ident(k)) || 0 -> 320 + 317 381878 1 : (ident(k) == 1111110) || 0 -> 320 + 318 381878 1 : (0 <= ident(j))) 0 -> 324 319 : { 320 381878 0 : j = j + 1; 321 : } 322 : 323 : /* third true */ + 324 381878 1 : if ((ident(j) >= 1111110) || 0 -> 329 + 325 381878 1 : (1111110 == ident(k)) || 0 -> 329 + 326 381878 1 : (ident(k) == 0) || 381878 -> 329 * 327 0 0 : (111110 <= ident(j))) 0 -> 333 328 : { 329 381878 0 : j = j + 1; 330 : } 331 : 332 : /* second true */ + 333 381878 1 : if ((ident(j) >= 1111110) || 0 -> 338 + 334 381878 1 : (0 == ident(k)) || 381878 -> 338 * 335 0 0 : (ident(k) == 1111110) || 0 -> 338 * 336 0 0 : (111110 <= ident(j))) 0 -> 342 337 : { 338 381878 0 : j = j + 1; 339 : } 340 : 341 : /* first true */ + 342 381878 1 : if ((ident(j) >= 0) || 381878 -> 347 * 343 0 0 : (1111110 == ident(k)) || 0 -> 347 * 344 0 0 : (ident(k) == 1111110) || 0 -> 347 * 345 0 0 : (111110 <= ident(j))) 0 -> 350 346 : { 347 381878 0 : j = j + 1; 348 : } 349 : + 350 381878 1 : if ((j < 0) && (ident(k) == 0)) 381878 -> 355 0 -> 355 351 : { * 352 0 0 : j = j + 1; 353 : } 354 : + 355 381878 2 : if ((j >= 0) && (ident(k) != 0)) 0 -> 360 381878 -> 360 356 : { * 357 0 0 : j = j + 1; 358 : } 359 : + 360 381878 2 : if ((j >= 0) && (ident(k) == 0)) 0 -> 366 0 -> 366 361 : { 362 381878 0 : j = j + 1; 363 : } 364 : 365 : /* all true */ + 366 381878 1 : if ((ident(j) >= 0) && 0 -> 375 + 367 381878 1 : (ident(k) == 0) && 0 -> 375 + 368 381878 1 : (0 == ident(k)) && 0 -> 375 + 369 381878 1 : (0 <= ident(j))) 0 -> 375 370 : { 371 381878 0 : j = j + 1; 372 : } 373 : 374 : /* fourth false */ + 375 381878 1 : if ((ident(j) >= 0) && 0 -> 384 + 376 381878 1 : (ident(k) == 0) && 0 -> 384 + 377 381878 1 : (0 == ident(k)) && 0 -> 384 + 378 381878 1 : (10000 <= ident(j))) 381878 -> 384 379 : { * 380 0 0 : j = j + 1; 381 : } 382 : 383 : /* third false */ + 384 381878 1 : if ((ident(j) >= 0) && 0 -> 393 + 385 381878 1 : (ident(k) == 0) && 0 -> 393 + 386 381878 1 : (5555 == ident(k)) && 381878 -> 393 * 387 0 0 : (0 <= ident(j))) 0 -> 393 388 : { * 389 0 0 : j = j + 1; 390 : } 391 : 392 : /* second false */ + 393 381878 1 : if ((ident(j) >= 0) && 0 -> 402 + 394 381878 1 : (ident(k) == 0) && 0 -> 402 + 395 381878 1 : (0 == ident(k)) && 0 -> 402 + 396 381878 1 : (0 <= ident(j))) 0 -> 402 397 : { 398 381878 0 : j = j + 1; 399 : } 400 : 401 : /* first false */ + 402 381878 1 : if ((ident(j) >= 10000) && 381878 -> 410 * 403 0 0 : (ident(k) == 0) && 0 -> 410 * 404 0 0 : (0 == ident(k)) && 0 -> 410 * 405 0 0 : (0 <= ident(j))) 0 -> 410 406 : { * 407 0 0 : j = j + 1; 408 : } 409 : 410 381878 0 : return j; 411 381878 0 : } 412 : 413 : int main(int argc, char **argv) 414 : { 415 : int i; 416 : 417 : int loop_count = 10; 418 : 419 : if (argc > 1) loop_count = atoi(argv[1]); 420 : 421 : for (i = 0; i < loop_count; i++) 422 : { 423 : StraightLineFunc(i); 424 : LoopFunc(i); 425 : SwitchFunc(i); 426 : LoopSwitchFunc(i); 427 : IfFunc(i); 428 : ExprFunc(i); 429 : } 430 : 431 : return i; 432 : } 433 : 434 : O - Number of offsets for line B - Number of branches for line I - Number of offsets/branches instrumented I% - Percentage of offsets/branches instrumented H - Number of offsets/branches hit H% - Percentage of offsets/branches hit T - Number of branches taken N - Number of branches not taken + - Partial coverage on this line * - No coverage on this line