software-engineering testing

Definition

Definition-Use Pair

A Definition-Use Pair (DU Pair) is a concept in data flow testing that connects the definition of a variable (where it is assigned a value) to its usage (where that value is read).

A DU pair for variable is a tuple , where:

  1. is a node in the CFG where is defined.
  2. is a node in the CFG where is used.
  3. There exists a definition-clear path from to .

Concepts

Variable Definition & Use

  • Definition (): Assignment, parameter, input read (e.g., x = 1, read(x)).
  • Use (): Computation, condition, output (e.g., y = x + 1, if (x > 0)).

Definition-Clear Path

A path is definition-clear for if no other node on the path re-defines . If were re-defined at node (where ), then the use at would rely on the value from , not .

Reaching Definitions Analysis

DU pairs are computed with a reaching-definitions static analysis. For each node and variable , it computes all definitions of that possibly reach via a definition-clear path.

Definitions:

  • : Predecessors of .
  • : Successors of .
  • : Definitions generated in .
  • : Definitions killed in .

Algorithm (Fixpoint Iteration): We compute two sets for every node:

  1. : The reaching definitions at the beginning of .
  1. : The reaching definitions at the end of .

Metrics

DU-Pairs Coverage

The percentage of all feasible valid DU pairs that are exercised by the test suite.

  • Strength: Stronger than branch coverage and can be equivalent to path coverage in specific cases, but generally more focused on data dependencies.

Example

Example: Simple

1: x = 1;
2: y = 1;
3: if (a) {
4:    x = 0;
5: }
6: return x;

DU Pairs for x:

  1. Def at 1: x = 1 reaches usage at 6 if path is (Branch a is False).
    • Pair: .
  2. Def at 4: x = 0 reaches usage at 6 if path is (Branch a is True).
    • Pair: .

DU Pairs for y:

  • Def at 2: y = 1.
  • Use: None.
  • Result: No DU pairs for y.

Coverage Analysis: To achieve 100% DU-Pairs Coverage for x, we need a test where a is True (executes pair ) and a test where a is False (executes pair ).

Example: Invoice Calculation

Exercise 5: Data Flow Coverage

You are given the following function calculateInvoice and an initial test suite.

01 int calculateInvoice(int items, boolean isVIP) {
02   int total = 0;        // d1
03   int surcharge = 0;    // d5
04
05   for (int i = 1; i <= items; i++) {
06     total += 100;       // d2
07
08     if (i % 3 == 0) {
09       surcharge += 20;  // d6
10     } else {
11       surcharge += 10;  // d7
12     }
13   }
14
15   if (isVIP) {
16     total = total - 50; // d3
17   }
18
19   total += surcharge;   // d4
20   return total;
21 }

Initial Tests:

  • T1: items = 0, isVIP = false
  • T2: items = 1, isVIP = false

a) Control Flow Graph (CFG):

We define the following Basic Blocks (BB):

  • BB0 (Entry): Lines 1-5 (initialisation).
  • BB1 (Loop Header): Line 5 (condition i <= items).
  • BB2 (Loop Body Start): Line 6 (total += 100) and 8 (condition i % 3 == 0).
  • BB3 (If True): Line 9 (surcharge += 20).
  • BB4 (If False): Line 11 (surcharge += 10).
  • BB5 (Loop Increment): Line 5 (i++).
  • BB6 (After Loop): Line 15 (condition isVIP).
  • BB7 (VIP Branch): Line 16 (total -= 50).
  • $BB8 (Exit): Line 19 (total += surcharge) and 20 (return).

Graph:

graph TD
    Entry((Entry)) --> BB0["BB<sub>0</sub>: total=0; sur=0; i=1"]
    BB0 --> BB1{"BB<sub>1</sub>: i <= items"}
    BB1 -- "True" --> BB2{"BB<sub>2</sub>: total+=100; i%3==0"}
    BB1 -- "False" --> BB6{"BB<sub>6</sub>: isVIP"}
    BB2 -- "True" --> BB3["BB<sub>3</sub>: sur+=20"]
    BB2 -- "False" --> BB4["BB<sub>4</sub>: sur+=10"]
    BB3 --> BB5["BB<sub>5</sub>: i++"]
    BB4 --> BB5
    BB5 --> BB1
    BB6 -- "True" --> BB7["BB<sub>7</sub>: total-=50"]
    BB6 -- "False" --> BB8["BB<sub>8</sub>: total+=sur; return"]
    BB7 --> BB8
    BB8 --> Exit((Exit))

b) Reaching Definitions:

Definitions:

  • total: (Line 2), (Line 6), (Line 16), (Line 19).
  • surcharge: (Line 3), (Line 9), (Line 11).

Analysis Table:

Node Reach() (In)ReachOut() (Out)
BB0
BB1
BB2 (kills )
BB3 (kills )
BB4 (kills )
BB5
BB6
BB7 (kills )
BB8 (kills )

How to build this table?

The table is constructed iteratively until the sets stop changing (fixpoint).

  1. Reach(n) comes from predecessors:
    • Example for BB1: It has predecessors BB0 and BB5.
    • .
    • .
  2. ReachOut(n) applies changes within the block:
    • Formula: .
    • Example for BB2:
    • Input: .
    • Kill: Line 6 defines total (), so it kills all other definitions of total ( from Line 2).
    • Gen: Line 6 generates .
    • Result: Remove , add , keep everything else ().
    • .

c) DU-Pairs and Coverage:

1. List of DU-Pairs:

Variable total:

  • : Feasible ().
  • : Feasible ().
  • : Feasible ().
  • : Feasible ().
  • : Feasible ().
  • : Feasible ().
  • : Feasible ().
  • : Feasible (Always).

Variable surcharge:

  • : Feasible (, reaches Line 11).
  • : Infeasible. Requires to satisfy (Impossible).
  • : Feasible ().
  • : Feasible ().
  • : Feasible ().
  • : Infeasible. Requires and (Impossible).
  • : Feasible ().
  • : Feasible (End on loop index not div by 3).
  • : Feasible (End on loop index div by 3).

2. Coverage of Initial Tests:

  • T1 (items=0, !VIP): Path .
    • Covers: total ; surcharge .
  • T2 (items=1, !VIP): Path .
    • Covers: total ; surcharge .

Executed Pairs: .
Total Feasible Pairs: 15 (8 for total + 7 for surcharge).
Coverage: .

3. Extending the Test Suite:

To achieve 100% coverage, we need to cover the remaining pairs:

  • total: .
  • surcharge: .

New Tests:

  • T3 (items=0, VIP): Covers .
  • T4 (items=4, VIP):
    • Loop: (L11), (L11), (L9), (L11).
    • Covers:
      • total: (multiple iterations), (after loop).
      • surcharge: (), (), (), (end).
  • T5 (items=3, !VIP):
    • Loop: . Ends on 3 (L9).
    • Covers: surcharge .

4. Feasibility:
Achieving 100% DU-pair coverage is not always possible due to infeasible paths. In this example, pairs like and are infeasible because the logic () and the loop counter initialization prevent those specific definition-use combinations from ever being executed.