Skip to content

Why do we need yet another *cov? #7

@whentojump

Description

@whentojump

Reason 1: Source based

Example 1

https://elixir.bootlin.com/linux/v6.10-rc7/source/drivers/gpu/drm/drm_buddy.c#L114

GCC gcov report:

        -:  105:static struct drm_buddy_block *
        -:  106:__get_buddy(struct drm_buddy_block *block)
        -:  107:{
        -:  108:	struct drm_buddy_block *parent;
        -:  109:
    #####:  110:	parent = block->parent;
    #####:  111:	if (!parent)
        -:  112:		return NULL;
        -:  113:
   12568*:  114:	if (parent->left == block)
branch  0 never executed (fallthrough)
branch  1 never executed
branch  2 never executed (fallthrough)
branch  3 never executed
branch  4 never executed (fallthrough)
branch  5 never executed
branch  6 taken 9 (fallthrough)
branch  7 taken 1037
branch  8 taken 5226 (fallthrough)
branch  9 taken 6296
    5235*:  115:		return parent->right;
        -:  116:
        -:  117:	return parent->left;
        -:  118:}

Confusing part(s):

  • Statement coverage: covered lines (L114) can be found after uncovered lines (L110)
  • Branch coverage: a simple if statement (L114) is reported to have 10 branches instead of 2

Clang Source-based Code Coverage report:

  105|       |static struct drm_buddy_block *
  106|       |__get_buddy(struct drm_buddy_block *block)
  107|  12.6k|{
  108|  12.6k|	struct drm_buddy_block *parent;
  109|       |
  110|  12.6k|	parent = block->parent;
  111|  12.6k|	if (!parent)
  ------------------
  |  Branch (111:6): [True: 0, False: 12.6k]
  ------------------
  112|      0|		return NULL;
  113|       |
  114|  12.6k|	if (parent->left == block)
  ------------------
  |  Branch (114:6): [True: 5.27k, False: 7.37k]
  ------------------
  115|  5.27k|		return parent->right;
  116|       |
  117|  7.37k|	return parent->left;
  118|  12.6k|}

Example 2

https://elixir.bootlin.com/linux/v6.10-rc7/source/drivers/leds/led-triggers.c#L33

GCC gcov report:

        -:   30:static inline bool
        -:   31:trigger_relevant(struct led_classdev *led_cdev, struct led_trigger *trig)
        -:   32:{
       3*:   33:	return !trig->trigger_type || trig->trigger_type == led_cdev->trigger_type;
branch  0 taken 0 (fallthrough)
branch  1 taken 3
branch  2 never executed (fallthrough)
branch  3 never executed
branch  4 never executed (fallthrough)
branch  5 never executed
branch  6 never executed (fallthrough)
branch  7 never executed
branch  8 never executed (fallthrough)
branch  9 never executed
branch 10 never executed (fallthrough)
branch 11 never executed
        -:   34:}

Confusing part(s):

  • Branch coverage: a logical expression with 2 leaf conditions is reported to have 12 branches instead of 4

Clang Source-based Code Coverage report:

   30|       |static inline bool
   31|       |trigger_relevant(struct led_classdev *led_cdev, struct led_trigger *trig)
   32|      3|{
   33|      3|	return !trig->trigger_type || trig->trigger_type == led_cdev->trigger_type;
  ------------------
  |  Branch (33:9): [True: 3, False: 0]
  |  Branch (33:32): [True: 0, False: 0]
  ------------------
   34|      3|}

Example 3

https://elixir.bootlin.com/linux/v6.10-rc7/source/drivers/firmware/dmi_scan.c#L1068

GCC gcov report:

        5: 1068:	if (s == e || *e != '/' || !month || month > 12) {
branch  0 taken 5 (fallthrough)
branch  1 taken 0
branch  2 taken 5 (fallthrough)
branch  3 taken 0
branch  4 taken 0 (fallthrough)
branch  5 taken 5

Confusing part(s):

  • Branch coverage: a logical expression with 4 leaf conditions is reported to have 6 branches instead of 8.

Clang Source-based Code Coverage report:

 1068|      5|	if (s == e || *e != '/' || !month || month > 12) {
  ------------------
  |  Branch (1068:6): [True: 0, False: 5]
  |  Branch (1068:16): [True: 0, False: 5]
  |  Branch (1068:29): [True: 0, False: 5]
  |  Branch (1068:39): [True: 0, False: 5]
  ------------------

Example 4

https://elixir.bootlin.com/linux/v6.10-rc7/source/fs/xattr.c#L30

GCC gcov report:

     9120:   33:	while (*a_prefix && *a == *a_prefix) {
condition outcomes covered 4/6
condition  1 not covered (false)
condition  2 not covered (false)

Confusing part(s):

  • MC/DC: a logical expression with 2 leaf conditions is reported to have 6 condition outcomes instead of 4.

Clang Source-based Code Coverage report:

   33|  1.53k|	while (*a_prefix && *a == *a_prefix) {
  ------------------
  |---> MC/DC Decision Region (33:9) to (33:37)
  |
  |  Number of Conditions: 2
  |     Condition C1 --> (33:9)
  |     Condition C2 --> (33:22)
  |
  |  Executed MC/DC Test Vectors:
  |
  |     C1, C2    Result
  |  1 { F,  -  = F      }
  |  2 { T,  F  = F      }
  |  3 { T,  T  = T      }
  |
  |  C1-Pair: covered: (1,3)
  |  C2-Pair: covered: (2,3)
  |  MC/DC Coverage for Decision: 100.00%
  |
  ------------------

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions