jacoco / jacoco/jacoco

Should ignore `kotlin.KotlinNothingValueException` throwing code, that is generated code (by Kotlin compiler)

Open
#1,589 1 comment 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

language: Kotlin type: enhancement
Dominant language
Java
Stars
4.6k
Forks
1.2k
Avg merge
1d 9h
Merged PRs (30d)
23

Description

Scenario
  • JaCoCo version: 0.8.11.202310140853
  • Operating system: Any (confirmed with Linux and Mac)
  • Tool integration: Any (confirmed with Gradle)
  • Description of your use case:
    1. Write a Kotlin method that throws exception always and has Nothing return type
    • e.g. fun throwSomeException(): Nothing { throw RuntimeException("this method never returns and always throws") }
    • Kotlin Nothing means it never returns (always throws an exception), and Kotlin compiler ensure the method always throws
    1. Call the method and measure coverage of the caller-side code
    2. JaCoCo test report marks the row with yellow "1 or 2 branch missed"

Example:

// Code in /src/main/kotlin

fun fail(): Nothing {
  throw RuntimeException("Nothing means this method always throws and never returns")
}

fun doSomething(flag: Boolean) {
  if(flag) {
    fail() // For this code line, even if test code covers both flag == true and false cases, JaCoCo test report says "1 or 2 branch missed"
  }
}
// Code in /src/test/kotlin

/** Test code should yield 100% coverage of the doSomething method */
@Test
fun test() {
   doSomething(false)
   Assertions.assertThrows(RuntimeException::class.java) { doSomething(true) }
}
Current Behaviour

For every code lines calling Kotlin Nothing returning method, JaCoCo reports "1 or 2 branch missed".

This looks caused by Kotlin compiler generated safety-guard code, that throws kotlin.KotlinNothingValueException in case of if the Nothing returning method haven't thrown exception.

As looking JVM bytecode of the caller-side, the bytecode looks like this:

    INVOKESTATIC ...my method that always throws and returns Nothing...
    NEW kotlin/KotlinNothingValueException
    DUP
    INVOKESPECIAL kotlin/KotlinNothingValueException.<init> ()V
    ATHROW

The NEW kotlin/KotlinNothingValueException and following code lines never runs practically because the codes follows Nothing returning method call that always throws exception.

Wanted Behaviour

For every code lines calling Kotlin Nothing returning method, JaCoCo should ignore kotlin.KotlinNothingValueException related compiler-generated codes.

Possible Workarounds
  • tolerate poor coverage percentage of generated report
  • avoid using Nothing language feature of Kotlin

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the Kotlin Nothing example with JaCoCo and inspect the caller-side JVM bytecode around the INVOKESTATIC call and the generated NEW kotlin/KotlinNothingValueException sequence. Trace how JaCoCo turns this sequence into branch coverage in the report. Done means the generated safety-guard code is excluded without hiding coverage for the surrounding Kotlin code.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, kotlin
Domain
devtools, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.