diff --git a/utbot-core/src/main/kotlin/org/utbot/common/HackUtil.kt b/utbot-core/src/main/kotlin/org/utbot/common/HackUtil.kt index 3b9eb2e827..881b708f55 100644 --- a/utbot-core/src/main/kotlin/org/utbot/common/HackUtil.kt +++ b/utbot-core/src/main/kotlin/org/utbot/common/HackUtil.kt @@ -25,26 +25,46 @@ inline fun heuristic(reason: WorkaroundReason, block: () -> T): T = block() /** * Explains reason for applied workaround. - * - * Workarounds are: - * - HACK - hacks behaviour for contest. Shall be removed sometimes - * - MAKE_SYMBOLIC - Returns a new symbolic value with proper type instead of function result (i.e. for wrappers) - * - IGNORE_SORT_INEQUALITY -- Ignores pairs of particular sorts in stores and selects - * - RUN_CONCRETE -- Runs something concretely instead of symbolic run - * - REMOVE_ANONYMOUS_CLASSES -- Remove anonymous classes from the results passed to the code generation till it doesn't support their generation - * - IGNORE_MODEL_TYPES_INEQUALITY -- Ignore the fact that model before and model after have different types - * - LONG_CODE_FRAGMENTS -- Comment too long blocks of code due to JVM restrictions [65536 bytes](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.3) - * - ARRAY_ELEMENT_TYPES_ALWAYS_NULLABLE -- Can't infer nullability for array elements from allocation statement, so make them nullable - * Note: - * - MAKE_SYMBOLIC can lose additional path constraints or branches from function call */ enum class WorkaroundReason { + /** + * Hacks behaviour for contest. Shall be removed sometimes + */ HACK, + /** + * Returns a new symbolic value with proper type instead of function result (i.e. for wrappers) + * + * [MAKE_SYMBOLIC] can lose additional path constraints or branches from function call + */ MAKE_SYMBOLIC, + /** + * Ignores pairs of particular sorts in stores and selects + */ IGNORE_SORT_INEQUALITY, + /** + * Runs something concretely instead of symbolic run + */ RUN_CONCRETE, + /** + * Remove anonymous classes from the results passed to the code generation till it doesn't support their generation + */ REMOVE_ANONYMOUS_CLASSES, + /** + * Ignore the fact that model before and model after have different types + */ IGNORE_MODEL_TYPES_INEQUALITY, + /** + * Comment too long blocks of code due to JVM restrictions [65536 bytes](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.3) + */ LONG_CODE_FRAGMENTS, + /** + * Can't infer nullability for array elements from allocation statement, so make them nullable + */ ARRAY_ELEMENT_TYPES_ALWAYS_NULLABLE, + /** + * We won't branch on static field from trusted libraries and won't add them to staticsBefore. For now, it saves us + * from setting [SecurityManager] and other suspicious stuff, but it can lead to coverage regression and thus it + * requires thorough [investigation](https://github.com/UnitTestBot/UTBotJava/issues/716). + */ + IGNORE_STATICS_FROM_TRUSTED_LIBRARIES, } \ No newline at end of file diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt index b424be40ca..edbc16f2f5 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt @@ -389,6 +389,13 @@ object UtSettings { */ var skipTestGenerationForSyntheticMethods by getBooleanProperty(true) + /** + * Flag that indicates whether should we branch on and set static fields from trusted libraries or not. + * + * @see [org.utbot.common.WorkaroundReason.IGNORE_STATICS_FROM_TRUSTED_LIBRARIES] + */ + var ignoreStaticsFromTrustedLibraries by getBooleanProperty(true) + override fun toString(): String = settingsValues .mapKeys { it.key.name } diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Memory.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Memory.kt index 6f06ac74a7..b398b18b24 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Memory.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Memory.kt @@ -124,7 +124,7 @@ data class Memory( // TODO: split purely symbolic memory and information about s private val concrete: PersistentMap = persistentHashMapOf(), private val mockInfos: PersistentList = persistentListOf(), private val staticInstanceStorage: PersistentMap = persistentHashMapOf(), - private val initializedStaticFields: PersistentMap = persistentHashMapOf(), + private val initializedStaticFields: PersistentSet = persistentHashSetOf(), private val staticFieldsStates: PersistentMap = persistentHashMapOf(), private val meaningfulStaticFields: PersistentSet = persistentHashSetOf(), private val addrToArrayType: PersistentMap = persistentHashMapOf(), @@ -290,7 +290,7 @@ data class Memory( // TODO: split purely symbolic memory and information about s concrete = concrete.putAll(update.concrete), mockInfos = mockInfos.mergeWithUpdate(update.mockInfos), staticInstanceStorage = staticInstanceStorage.putAll(update.staticInstanceStorage), - initializedStaticFields = initializedStaticFields.putAll(update.initializedStaticFields), + initializedStaticFields = initializedStaticFields.addAll(update.initializedStaticFields), staticFieldsStates = previousMemoryStates.toPersistentMap().putAll(updatedStaticFields), meaningfulStaticFields = meaningfulStaticFields.addAll(update.meaningfulStaticFields), addrToArrayType = addrToArrayType.putAll(update.addrToArrayType), @@ -963,7 +963,7 @@ data class MemoryUpdate( val concrete: PersistentMap = persistentHashMapOf(), val mockInfos: PersistentList = persistentListOf(), val staticInstanceStorage: PersistentMap = persistentHashMapOf(), - val initializedStaticFields: PersistentMap = persistentHashMapOf(), + val initializedStaticFields: PersistentSet = persistentHashSetOf(), val staticFieldsUpdates: PersistentList = persistentListOf(), val meaningfulStaticFields: PersistentSet = persistentHashSetOf(), val addrToArrayType: PersistentMap = persistentHashMapOf(), @@ -982,7 +982,7 @@ data class MemoryUpdate( concrete = concrete.putAll(other.concrete), mockInfos = mockInfos.mergeWithUpdate(other.mockInfos), staticInstanceStorage = staticInstanceStorage.putAll(other.staticInstanceStorage), - initializedStaticFields = initializedStaticFields.putAll(other.initializedStaticFields), + initializedStaticFields = initializedStaticFields.addAll(other.initializedStaticFields), staticFieldsUpdates = staticFieldsUpdates.addAll(other.staticFieldsUpdates), meaningfulStaticFields = meaningfulStaticFields.addAll(other.meaningfulStaticFields), addrToArrayType = addrToArrayType.putAll(other.addrToArrayType), diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Traverser.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Traverser.kt index 3712db126b..0daa8e5098 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Traverser.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Traverser.kt @@ -1,12 +1,14 @@ package org.utbot.engine import kotlinx.collections.immutable.persistentHashMapOf +import kotlinx.collections.immutable.persistentHashSetOf import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.toPersistentList -import kotlinx.collections.immutable.toPersistentMap import kotlinx.collections.immutable.toPersistentSet import org.utbot.common.WorkaroundReason.HACK +import org.utbot.framework.UtSettings.ignoreStaticsFromTrustedLibraries +import org.utbot.common.WorkaroundReason.IGNORE_STATICS_FROM_TRUSTED_LIBRARIES import org.utbot.common.WorkaroundReason.REMOVE_ANONYMOUS_CLASSES import org.utbot.common.unreachableBranch import org.utbot.common.withAccessibility @@ -112,6 +114,7 @@ import soot.DoubleType import soot.FloatType import soot.IntType import soot.LongType +import soot.Modifier import soot.PrimType import soot.RefLikeType import soot.RefType @@ -560,7 +563,7 @@ class Traverser( } val initializedStaticFieldsMemoryUpdate = MemoryUpdate( - initializedStaticFields = staticFields.associate { it.first.fieldId to it.second.single() }.toPersistentMap(), + initializedStaticFields = staticFields.map { it.first.fieldId }.toPersistentSet(), meaningfulStaticFields = meaningfulStaticFields.map { it.first.fieldId }.toPersistentSet(), symbolicEnumValues = enumConstantSymbolicValues.toPersistentList() ) @@ -596,7 +599,7 @@ class Traverser( // Collects memory updates val initializedFieldUpdate = - MemoryUpdate(initializedStaticFields = persistentHashMapOf(fieldId to concreteValue)) + MemoryUpdate(initializedStaticFields = persistentHashSetOf(fieldId)) val objectUpdate = objectUpdate( instance = findOrCreateStaticObject(declaringClass.type), @@ -823,7 +826,7 @@ class Traverser( val staticFieldMemoryUpdate = StaticFieldMemoryUpdateInfo(fieldId, value) val touchedStaticFields = persistentListOf(staticFieldMemoryUpdate) queuedSymbolicStateUpdates += MemoryUpdate(staticFieldsUpdates = touchedStaticFields) - if (!environment.method.isStaticInitializer && !fieldId.isSynthetic) { + if (!environment.method.isStaticInitializer && isStaticFieldMeaningful(left.field)) { queuedSymbolicStateUpdates += MemoryUpdate(meaningfulStaticFields = persistentSetOf(fieldId)) } } @@ -1780,13 +1783,27 @@ class Traverser( queuedSymbolicStateUpdates += MemoryUpdate(staticFieldsUpdates = touchedStaticFields) // TODO filter enum constant static fields JIRA:1681 - if (!environment.method.isStaticInitializer && !fieldId.isSynthetic) { + if (!environment.method.isStaticInitializer && isStaticFieldMeaningful(field)) { queuedSymbolicStateUpdates += MemoryUpdate(meaningfulStaticFields = persistentSetOf(fieldId)) } return createdField } + /** + * For now the field is `meaningful` if it is safe to set, that is, it is not an internal system field nor a + * synthetic field. This filter is needed to prohibit changing internal fields, which can break up our own + * code and which are useless for the user. + * + * @return `true` if the field is meaningful, `false` otherwise. + */ + private fun isStaticFieldMeaningful(field: SootField) = + !Modifier.isSynthetic(field.modifiers) && + // we don't want to set fields from library classes + !workaround(IGNORE_STATICS_FROM_TRUSTED_LIBRARIES) { + ignoreStaticsFromTrustedLibraries && field.declaringClass.isFromTrustedLibrary() + } + /** * Locates object represents static fields of particular class. * @@ -3321,10 +3338,11 @@ class Traverser( val updatedFields = staticFieldsUpdates.mapTo(mutableSetOf()) { it.fieldId } val objectUpdates = mutableListOf() - // we assign unbounded symbolic variables for every non-final field of the class + // we assign unbounded symbolic variables for every non-final meaningful field of the class + // fields from predefined library classes are excluded, because there are not meaningful typeResolver .findFields(declaringClass.type) - .filter { !it.isFinal && it.fieldId in updatedFields } + .filter { !it.isFinal && it.fieldId in updatedFields && isStaticFieldMeaningful(it) } .forEach { // remove updates from clinit, because we'll replace those values // with new unbounded symbolic variable diff --git a/utbot-framework/src/test/kotlin/org/utbot/examples/collections/OptionalsTest.kt b/utbot-framework/src/test/kotlin/org/utbot/examples/collections/OptionalsTest.kt index baf628804b..73267d46f8 100644 --- a/utbot-framework/src/test/kotlin/org/utbot/examples/collections/OptionalsTest.kt +++ b/utbot-framework/src/test/kotlin/org/utbot/examples/collections/OptionalsTest.kt @@ -10,6 +10,7 @@ import org.utbot.examples.singleValue import org.utbot.framework.codegen.CodeGeneration import org.utbot.framework.plugin.api.CodegenLanguage import org.junit.jupiter.api.Test +import java.util.* class OptionalsTest : UtValueTestCaseChecker( Optionals::class, @@ -67,7 +68,7 @@ class OptionalsTest : UtValueTestCaseChecker( checkStatics( Optionals::createNullable, eq(2), - { value, statics, result -> value == null && result === statics.singleValue() }, + { value, _, result -> value == null && result === Optional.empty() }, { value, _, result -> value != null && result!!.get() == value }, coverage = DoNotCalculate ) @@ -78,7 +79,7 @@ class OptionalsTest : UtValueTestCaseChecker( checkStatics( Optionals::createEmpty, eq(1), - { statics, result -> result === statics.singleValue() }, + { _, result -> result === Optional.empty() }, coverage = DoNotCalculate ) } @@ -88,7 +89,7 @@ class OptionalsTest : UtValueTestCaseChecker( checkStatics( Optionals::createIntEmpty, eq(1), - { statics, result -> result === statics.singleValue() }, + { _, result -> result === OptionalInt.empty() }, coverage = DoNotCalculate ) } @@ -98,7 +99,7 @@ class OptionalsTest : UtValueTestCaseChecker( checkStatics( Optionals::createLongEmpty, eq(1), - { statics, result -> result === statics.singleValue() }, + { _, result -> result === OptionalLong.empty() }, coverage = DoNotCalculate ) } @@ -108,7 +109,7 @@ class OptionalsTest : UtValueTestCaseChecker( checkStatics( Optionals::createDoubleEmpty, eq(1), - { statics, result -> result === statics.singleValue() }, + { _, result -> result === OptionalDouble.empty() }, coverage = DoNotCalculate ) } @@ -119,7 +120,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::getValue, eq(3), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional != null && optional === statics.singleValue() && result == null }, + { optional, _, result -> optional != null && optional === Optional.empty() && result == null }, { optional, _, result -> optional != null && result == optional.get() }, coverage = DoNotCalculate ) @@ -131,7 +132,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::getIntValue, eq(3), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional != null && optional === statics.singleValue() && result == null }, + { optional, _, result -> optional != null && optional === OptionalInt.empty() && result == null }, { optional, _, result -> optional != null && result == optional.asInt }, coverage = DoNotCalculate ) @@ -143,7 +144,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::getLongValue, eq(3), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional != null && optional === statics.singleValue() && result == null }, + { optional, _, result -> optional != null && optional === OptionalLong.empty() && result == null }, { optional, _, result -> optional != null && result == optional.asLong }, coverage = DoNotCalculate ) @@ -155,7 +156,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::getDoubleValue, eq(3), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional != null && optional === statics.singleValue() && result == null }, + { optional, _, result -> optional != null && optional === OptionalDouble.empty() && result == null }, { optional, _, result -> optional != null && result == optional.asDouble }, coverage = DoNotCalculate ) @@ -167,7 +168,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::getWithIsPresent, eq(3), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional === statics.singleValue() && result == null }, + { optional, _, result -> optional === Optional.empty() && result == null }, { optional, _, result -> optional.get() == result }, coverage = DoNotCalculate ) @@ -179,7 +180,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::countIfPresent, eq(3), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional === statics.singleValue() && result == 0 }, + { optional, _, result -> optional === Optional.empty() && result == 0 }, { optional, _, result -> optional.get() == result }, coverage = DoNotCalculate ) @@ -191,7 +192,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::countIntIfPresent, ignoreExecutionsNumber, { optional, _, _ -> optional == null }, - { optional, statics, result -> optional === statics.singleValue() && result == 0 }, + { optional, _, result -> optional === OptionalInt.empty() && result == 0 }, { optional, _, result -> optional.asInt == result }, ) } @@ -202,7 +203,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::countLongIfPresent, ignoreExecutionsNumber, { optional, _, _ -> optional == null }, - { optional, statics, result -> optional === statics.singleValue() && result == 0L }, + { optional, _, result -> optional === OptionalLong.empty() && result == 0L }, { optional, _, result -> optional.asLong == result }, ) } @@ -213,7 +214,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::countDoubleIfPresent, ignoreExecutionsNumber, { optional, _, _ -> optional == null }, - { optional, statics, result -> optional === statics.singleValue() && result == 0.0 }, + { optional, _, result -> optional === OptionalDouble.empty() && result == 0.0 }, { optional, _, result -> optional.asDouble == result }, ) } @@ -224,9 +225,9 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::filterLessThanZero, eq(4), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional === statics.singleValue() && result === optional }, + { optional, _, result -> optional === Optional.empty() && result === optional }, { optional, _, result -> optional.get() >= 0 && result == optional }, - { optional, statics, result -> optional.get() < 0 && result === statics.singleValue() }, + { optional, _, result -> optional.get() < 0 && result === Optional.empty() }, coverage = DoNotCalculate ) } @@ -237,7 +238,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::absNotNull, eq(4), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional === statics.singleValue() && result === optional }, + { optional, _, result -> optional === Optional.empty() && result === optional }, { optional, _, result -> optional.get() < 0 && result!!.get() == -optional.get() }, { optional, _, result -> optional.get() >= 0 && result == optional }, coverage = DoNotCalculate @@ -250,8 +251,8 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::mapLessThanZeroToNull, eq(4), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional === statics.singleValue() && result === optional }, - { optional, statics, result -> optional.get() < 0 && result === statics.singleValue() }, + { optional, _, result -> optional === Optional.empty() && result === optional }, + { optional, _, result -> optional.get() < 0 && result === Optional.empty() }, { optional, _, result -> optional.get() >= 0 && result == optional }, coverage = DoNotCalculate ) @@ -263,7 +264,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::flatAbsNotNull, eq(4), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional === statics.singleValue() && result === optional }, + { optional, _, result -> optional === Optional.empty() && result === optional }, { optional, _, result -> optional.get() < 0 && result!!.get() == -optional.get() }, { optional, _, result -> optional.get() >= 0 && result == optional }, coverage = DoNotCalculate @@ -276,8 +277,8 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::flatMapWithNull, eq(5), { optional, _, _ -> optional == null }, - { optional, statics, result -> optional === statics.singleValue() && result === optional }, - { optional, statics, result -> optional.get() < 0 && result === statics.singleValue() }, + { optional, _, result -> optional === Optional.empty() && result === optional }, + { optional, _, result -> optional.get() < 0 && result === Optional.empty() }, { optional, _, result -> optional.get() > 0 && result == optional }, { optional, _, result -> optional.get() == 0 && result == null }, coverage = DoNotCalculate @@ -290,7 +291,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftOrElseRight, eq(3), { left, _, _, _ -> left == null }, - { left, right, statics, result -> left === statics.singleValue() && result == right }, + { left, right, _, result -> left === Optional.empty() && result == right }, { left, _, _, result -> left.isPresent && result == left.get() }, coverage = DoNotCalculate ) @@ -302,7 +303,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftIntOrElseRight, eq(3), { left, _, _, _ -> left == null }, - { left, right, statics, result -> left === statics.singleValue() && result == right }, + { left, right, _, result -> left === OptionalInt.empty() && result == right }, { left, _, _, result -> left.isPresent && result == left.asInt }, coverage = DoNotCalculate ) @@ -315,7 +316,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftLongOrElseRight, eq(3), { left, _, _, _ -> left == null }, - { left, right, statics, result -> left === statics.singleValue() && result == right }, + { left, right, _, result -> left === OptionalLong.empty() && result == right }, { left, _, _, result -> left.isPresent && result == left.asLong }, coverage = DoNotCalculate ) @@ -328,7 +329,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftDoubleOrElseRight, eq(3), { left, _, _, _ -> left == null }, - { left, right, statics, result -> left === statics.singleValue() && (result == right || result!!.isNaN() && right.isNaN()) }, + { left, right, _, result -> left === OptionalDouble.empty() && (result == right || result!!.isNaN() && right.isNaN()) }, { left, _, _, result -> left.isPresent && (result == left.asDouble || result!!.isNaN() && left.asDouble.isNaN()) }, coverage = DoNotCalculate ) @@ -341,7 +342,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftOrElseGetOne, eq(3), { left, _, _ -> left == null }, - { left, statics, result -> left === statics.singleValue() && result == 1 }, + { left, _, result -> left === Optional.empty() && result == 1 }, { left, _, result -> left.isPresent && result == left.get() }, coverage = DoNotCalculate ) @@ -353,7 +354,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftIntOrElseGetOne, eq(3), { left, _, _ -> left == null }, - { left, statics, result -> left === statics.singleValue() && result == 1 }, + { left, _, result -> left === OptionalInt.empty() && result == 1 }, { left, _, result -> left.isPresent && result == left.asInt }, coverage = DoNotCalculate ) @@ -365,7 +366,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftLongOrElseGetOne, eq(3), { left, _, _ -> left == null }, - { left, statics, result -> left === statics.singleValue() && result == 1L }, + { left, _, result -> left === OptionalLong.empty() && result == 1L }, { left, _, result -> left.isPresent && result == left.asLong }, coverage = DoNotCalculate ) @@ -377,7 +378,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftDoubleOrElseGetOne, eq(3), { left, _, _ -> left == null }, - { left, statics, result -> left === statics.singleValue() && result == 1.0 }, + { left, _, result -> left === OptionalDouble.empty() && result == 1.0 }, { left, _, result -> left.isPresent && result == left.asDouble }, coverage = DoNotCalculate ) @@ -389,7 +390,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftOrElseThrow, eq(3), { left, _, _ -> left == null }, - { left, statics, result -> left === statics.singleValue() && result == null }, + { left, _, result -> left === Optional.empty() && result == null }, { left, _, result -> left.isPresent && result == left.get() }, coverage = DoNotCalculate ) @@ -401,7 +402,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftIntOrElseThrow, eq(3), { left, _, _ -> left == null }, - { left, statics, result -> left === statics.singleValue() && result == null }, + { left, _, result -> left === OptionalInt.empty() && result == null }, { left, _, result -> left.isPresent && result == left.asInt }, coverage = DoNotCalculate ) @@ -413,7 +414,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftLongOrElseThrow, eq(3), { left, _, _ -> left == null }, - { left, statics, result -> left === statics.singleValue() && result == null }, + { left, _, result -> left === OptionalLong.empty() && result == null }, { left, _, result -> left.isPresent && result == left.asLong }, coverage = DoNotCalculate ) @@ -425,7 +426,7 @@ class OptionalsTest : UtValueTestCaseChecker( Optionals::leftDoubleOrElseThrow, eq(3), { left, _, _ -> left == null }, - { left, statics, result -> left === statics.singleValue() && result == null }, + { left, _, result -> left === OptionalDouble.empty() && result == null }, { left, _, result -> left.isPresent && result == left.asDouble }, coverage = DoNotCalculate )