Link Search Menu Expand Document

Kotlin Plugin

1.3.0

Requires pitest 1.16.0 or above

Enhancement: Optionally Filter All Null Handling

When activated, the kotlin_no_nulls feature will remove all mutations to null handling code for Kotlin classes. This will filter mutations to bytecode instructions produced by the compiler to implement Kotlin’s null safe type system, but also any hand rolled null checks.

This feature is not active by default. When the feature is not active, the plugin will filter null handling code more conservatively using its default settings.

1.2.6

Bug Fix: Boolean Logic In Compiler Suspend Function Code

The construction code to for inner classes used to implement suspend functions can sometimes contain boolean logic. Mutations to this compiler construct are now filtered.

1.2.5

Bug Fix: Suspend Function Filters Misses Generic Calls

The filter to remove mutations to suspend function state machine logic missed some mutations when the suspend function made a generic call. These mutations are now caught.

1.2.4

Enhancement: Filter Coroutine Suspended Checks

Suspend function junk mutation filtering now also picks up conditionals added by the compiler to check coroutine suspend state.

1.2.3

Enhancement: Improved Suspend Function Filtering

Improvements to arcmutate’s handling of suspend functions, reducing the number of remaining junk mutations.

1.2.2

Enhancement: Redundant Null Checks on Optionals

The Kotlin compiler will sometimes generate redundant null checks against values retrieved from Optional.get, resulting in unkillable mutants. These mutants are now automatically filtered.

Enhancement: Redundant Null Checks on Lists

In some circumstances the Kotlin compiler will sometimes generate redundant null checks against values retrieved from Lists of non-null types.

For example, the following code will generate a null check against the value retrieved from list

class HasNonNullableStringList {
    fun foo(list : List<String>?): String {
        val result = list?.get(0) ?: "fallback"
        return result
    }
}

Tests cannot distinguish mutations to this null check from the unmutated code as the Kotlin type system prevents the list from containing null.

These mutations can now be filtered by activating the feature KOTLIN_EXTRA. The filtering is disabled by default as it may also remove some legitimate mutations, it is up to the user to decide if this is acceptable for their context.

1.2.1

Bug Fix: Unkillable Mutants in when on sealed Class

For code such as

sealed class Foo {
    object A : Foo()
    object B : Foo()

    fun Foo?.toInt() : Int? =
        when(this) {
            A -> 0
            B -> 1
            null -> 42
        }
}

The Kotlin compiler requires the final null check, although this cannot be null. Mutations to this null check are now suppressed as the mutations are unkillable.

Only nulls in the final clause are supported by the filter, nulls placed earlier in the when clause will be mutated as normal.

1.2.0

Relocate Maven Co-ordinates

This release moves the plugin to com.arcmutate. Previous releases were published as com.groupcdg.pitest.

1.1.6

Bug Fix: Error when duplicate classes

If two projects contained a class of the same name in the same package, an error previously occured when aggregating them.

Although pitest cannot currently support aggregating projects that contain duplicate classes, an error is no longer thrown. When duplicate classes exist, aggregated results may not accurately report the coverage or mutations for either class.

1.1.5

Enhancement: Suppress mutations in logging lambdas

Pitest’s avoidCallsTo parameter accepts a list of classes. All code on the same line as a call to one of these classes is excluded from mutation.

The intended use for this parameter is to allow logging code to be excluded from analysis. This mechanism does not always work for Kotlin code however, as the compiler will generate a lambda method or inner function class when the logging method used accepts a Java Supplier or Kotlin function.

This release adds a filter to ensure lambdas are treated in the same fashion as simple method calls.

Enhancement: Suppress mutations to bufferedReader extension function code

Junk mutations in the bytecode generated for bufferedReader extension function calls are now suppressed.

1.1.4

Bug Fix: Methods not mutated when proxy generated

Arcmutate’s inline function filtering way incorrectly supressing mutations in methods using method references, where the kotlin compiler generated a synthetic lamba proxy for the call.

Enhancement: Suppress mutations to bufferedWriter extension function code

Junk mutations in the bytecode generated for bufferedWriter extension function calls are now suppressed.

1.1.3

Bug Fix: Kotlin remove distinct and sorted not auto activated

The Kotlin specific mutators were not auto activating when their extended set equivalents were activated via a group.

1.1.2

Enhancement: Remove distinct and sort calls on Kotlin Lists

This release adds two new mutators

  • KOTLIN_REMOVE_SORTED
  • KOTLIN_REMOVE_DISTINCT

Which remove calls to sorted and distinct on Kotlin lists. The mutators are activated automatically when the REMOVE_DISTINCT and REMOVE_SORTED mutators from the extended set are activated.

Bug Fix: Unkillable Mutants in when on sealed Class

For code such as

sealed class Foo {
    object A : Foo()
    object B : Foo()
    object C : Foo()
}

fun map(foo : Foo) : Int = when(foo) {
    is Foo.A -> 1
    is Foo.B -> 12
    is Foo.C -> 42
}

The Kotlin compiler generates equality checks in the final branch which are redundant as no further values are possible. Mutations to this bytecode resulted in unkillable mutants. These mutants are now suppressed.

1.1.1

Bug Fix: Unkillable Mutants in when on String

For code such as the following

when(s) {
    "a" -> 1
    "b" -> 2
    "c" -> 42
}

The kotlin compiler generates bytecode similar to a Java switch on string statement. This consists of a tableswitch instruction based on the string hashcodes, followed by a series of equality checks.

Mutating the equality checks does not produce useful mutations as, unless the test suite provides strings with hash collisions as inputs, these conditionals are never executed.

Rather than create unkillable mutants, these mutations are now suppressed.

1.1.0

Enhancement: Pitest 1.15.0 compatibility

This release updates the Kotlin plugin for compatibility with the breaking api changes in pitest 1.15.0. This release will not work with earlier versions of pitest.

1.0.8

1.0.7

Enhancement: Fail Cleanly When Pitest Version Too Low

The Kotlin plugin requires pitest 1.11.0 or later. The plugin will now fail with an error directing the user to update pitest if an incompatible version is used.

If the plugin is not supplied with the project base dir and dynamic licensing is not being used, it must search backwards for a licence file. This release expands the scope of that search.

1.0.6

Bug Fix: Extension Function Calls Marked As Inlined

The “inlined” marker was being incorrectly added to calls to extension functions.

Enhancement: Increase Default Maximum Method Size

The default maxMethodSize has been increased from 200 to 500 instructions. This higher limit should not cause issues for most projects and removes the need to add custom configuration for many users.

Enhancement: More Accurate Offset Calculation

The algorithm to align bytecode between inline code definitions and calls has been made more accurate at the cost of slightly more computationally expensive.

1.0.5

Enhancement: Reduce File IO

Reduce file io during static analysis. This may result in performance improvements for projects with large classpaths.

1.0.4

Enhancement: Static Analysis Performance Improvements

Significant reduction in static analysis time for some project.

1.0.3

Enhancement: Apply Size Limit To Inline Functions

To prevent large inline functions dominating analysis time, inline functions larger than 200 instructions will not be mutated by default. This limit can be configured with a pitest feature string.

e.g.

+KOTLIN(maxMethodSize[50])

Enhancement: Shortcut Static Analysis

Expensive static analysis is now avoided for some forms of inline code.

1.0.2

Bug Fix: Poor Performance Analysing Large Methods

Fix for poor scaling of some junk mutation filters with method size. We recommend also upgrading to pitest 1.11.5 which fixes similar issues in the core filters.

1.0.1

Note, although this release is compatible with pitest 1.11.0, we recommend using 1.11.3 or above as it contains bug fixes which impact on Kotlin projects.

Enhancement: Filter Kotlin Bridge Methods

The Kotlin compiler generates bridge methods when inheriting from some classes such as kotlin.Number, resulting in junk mutations. These are now filtered.

Bug Fix: Incremental Mutants Assigned To Wrong File

When using pitest incremental analysis, some mutants were assigned to the wrong source file in the HTML report as the original grouping of mutants was lost when analysing for inlined code.

Bug Fix: Over Inclusion of Inlined Test Classes

In order to handle inline functions, arcmutate must mutate bytecode from the test tree when it contains code inlined from the project under test. This logic was including inline code not currently targeted for mutation.

1.0.0

This release requires pitest 1.11.0 or higher.

Enhancement: Improved Inline Function Support

This release adds support for mutating inlined functions. Previously this was not possible as the bytecode within an inlined function is not executed by the JVM. Instead, multiple copies of the code are executed embedded within the function’s clients.

Analysis results for inlined copies of mutants are now seamlessly combined and rewritten to appear to occur in the original inline function. Line coverage is also rewritten so that inline the code will appear to have been executed if one or more of the embedded copies have been run.

0.2.2

Bug Fix: Support Late Init Bytecode for Kotlin 1.7+

Since 1.7, the Kotlin compiler produces slightly different bytecode for late initialized variables which was not picked up by the junk mutation filters in previous releases.

0.2.1

Enhancement: Further Improvements to Inlined Code Support

0.2.0

Require Pitest 1.9.5 or Above

Enhancement: Dynamic Licence Retrieval

See Licence Management for details.

0.1.4

Enhancement: Improvements to Inlined Code Support

0.1.3

New Feature: Stable Range Returns

Functions returning the following types

  • IntRange
  • LongRange
  • CharRange
  • Sequence
  • CoroutineContex

Will be mutated to return their “zero values” in place of the null mutation generated by standard pitest.

Enhancement: Infer Non Nullable Returns When Annotation Absent

For public functions which cannot return null, the Kotlin compiler will add a org.jetbrains.annotations.NotNull annotation. When this annotation is present, pitest will filter out mutations which would violate this constraint. The annotation is not added for private methods however.

This change uses other bytecode markers to infer if a return type is nullable and filter mutants accordingly.

0.1.2

New Feature: Inlined Code Support

See Inlined Functions