# BranchCoverage.dfy, Execution Coverage

    // RUN: %dafny /useBaseNameForFileName /compile:3 /coverage:- /spillTargetCode:1 /compileTarget:cs %S/BranchCoverage2.cs "%s" > "%t"
    // RUN: %dafny /useBaseNameForFileName /compile:3 /coverage:- /spillTargetCode:1 /compileTarget:js %S/BranchCoverage3.js "%s" >> "%t"
    // RUN: %dafny /useBaseNameForFileName /compile:3 /coverage:- /spillTargetCode:1 /compileTarget:go %S/BranchCoverage4.go "%s" >> "%t"
    // RUN: %dafny /useBaseNameForFileName /compile:3 /coverage:- /spillTargetCode:1 /compileTarget:java %S/CodeCoverage.java "%s" >> "%t"
    // RUN: %dafny /useBaseNameForFileName /compile:3 /coverage:- /spillTargetCode:1 /compileTarget:py %S/BranchCoverage.py "%s" >> "%t"
    // RUN: %diff "%s.expect" "%t"

    // The Main method is at the end of this file, because that makes it easier to maintain
    // this test file when adding more tests.

    // ---------- class constructor ----------

    class MyClass {
      constructor () {  // 3 times
      }
    }

    // ---------- routines that are never called ----------

    method NeverCalled() {
      // we get here 0 times
    }

    function FunctionNeverCalled(): int {
      // we get here 0 times
      75
    }

    // ---------- if ----------

    method M(x: int) returns (y: int) {
      // we get here 3 times
      if x < 10 {
        return x + 20;  // we get here 1 time
      } else if x < 20 {  // note: the location between th "else" and the "if" does not get recorded
        return x + 20;  // we get here 0 times
      } else {
        return 100;  // we get here 2 times
      }
    }

    method N(x: int) returns (y: int) {
      // we get here 3 times
      y := 100;
      if x < 10 {
        return x + 20;  // we get here 1 time
      } else if x < 20 {  // note: the location between th "else" and the "if" does not get recorded
        return x + 20;  // we get here 0 times
      }  // we get to this implicit else 2 times
    }

    method P(x: int) {
      // we get here 1 time
      var y := 100;
      if * {
        // we get here 0 times, because the compiler picks the other branch, which is empty
        y := y + 2;
      }  // we get to the implicit else 1 time

      if * {
        // we get here 1 time
      } else {
        // we get here 0 times, because the compiler picks the other branch, which is empty
        y := y + 2;
      }

      // the following if is all ghost, so there are no branch-coverage locations in it
      if x < 2 {
      } else if * {
      }

      if x < 2 {
        // get here 0 times
      } else if * {
        // we get here 0 times
        y := y + 1;
      }  // implicit else: 1 time
    }

    // ---------- if case ----------

    method Q(x: int) returns (y: int) {
      // we get here 3 times

      // the following statement is all ghost, so there are no coverage locations in it
      if {
        case x < 100 =>
        case x < 1000 =>
          assert x < 1_000_000;
        case 50 <= x =>
      }

      if
      case x < 100 =>
        // we get here 1 time
      case x < 1000 =>
        // we get here 1 time, since the compiler lays down the cases in order
        return 8;
      case 50 <= x =>
        // we get here 1 time
    }

    // ---------- while ----------

    method R(x: int) returns (y: int) {
      // we get here 1 time
      var i: nat := 0;
      while i < x {
        // we get here 111 times
        i := i + 1;
      }

      while * {
        // we get here 0 times
        break;
      }

      while
        decreases i
      {
        case i % 2 == 0 =>
          // we get here 56 times
          if i == 0 {
            // we get here 1 time
            break;
          }  // implicit else: 55 times
          i := i - 1;
        case i % 4 == 1 =>
          // we get here 28 times
          i := i - 1;
        case 0 < i =>
          // we get here 28 times
          i := i - 1;
      }

      return 40;
    }

    // ---------- top-level if-then-else ----------

    function Fib(n: nat): nat {
      // we get here 465 times
      if n < 2 then  // then: 233 times
        n
      else if false then  // then: 0 times (else-if is omitted)
        8
      else  // else: 232 times
        Fib(n - 2) + Fib(n - 1)
    }

    // ---------- top-level match expression, match statement, and tail recursion ----------

    function {:tailrecursion} Factorial(n: nat): nat {
      // 11 times
      match n
      case 0 => 1  // 1 time
      case _ => n * Factorial(n - 1)  // 10 times
    }

    method {:tailrecursion} ComputeFactorial(n: nat, acc: nat) returns (f: nat)
      ensures f == Factorial(n) * acc
    {
      // 11 times
      match n
      case 0 =>  // 1 time
        return acc;
      case _ =>  // 10 times
        f := ComputeFactorial(n - 1, acc * n);
    }

    // ---------- Main ----------

    method Main() {
      // we get here 1 time

      var mc := new MyClass();
      mc := new MyClass();
      mc := new MyClass();

      var y := M(5);
      y := M(y);
      y := M(y);

      y := N(5);
      y := N(y);
      y := N(y);

      P(5);

      y := Q(50);
      y := Q(101);
      y := Q(1010);

      y := R(111);

      y := Fib(12);

      y := Factorial(10);
      y := ComputeFactorial(10, 1);
    }