From 390bdea5f9e6b2931c6515a3016d532795dbb0a6 Mon Sep 17 00:00:00 2001 From: Alexey Menshutin Date: Fri, 6 Jan 2023 14:24:52 +0800 Subject: [PATCH 1/3] Add options for clinit sections --- .../kotlin/org/utbot/framework/UtSettings.kt | 13 +++++ .../testcheckers/SettingsModificators.kt | 21 ++++++++ .../objects/ClassForTestClinitSectionsTest.kt | 53 +++++++++++++++++++ .../main/kotlin/org/utbot/engine/Traverser.kt | 8 +++ .../objects/ClassForTestClinitSections.java | 13 +++++ 5 files changed, 108 insertions(+) create mode 100644 utbot-framework-test/src/test/kotlin/org/utbot/examples/objects/ClassForTestClinitSectionsTest.kt create mode 100644 utbot-sample/src/main/java/org/utbot/examples/objects/ClassForTestClinitSections.java 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 548bb32b55..7b68eb7740 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 @@ -505,6 +505,19 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS * The behaviour of further analysis if tests generation cancellation is requested. */ var cancellationStrategyType by getEnumProperty(CancellationStrategyType.SAVE_PROCESSED_RESULTS) + + /** + * Depending on this option, sections might be analyzed or not. + * Note that some clinit sections still will be initialized using runtime information. + */ + var disableClinitSectionsAnalysis by getBooleanProperty(false) + + /** + * Process all clinit sections concretely. + * + * If [disableClinitSectionsAnalysis] is true, it disables effect of this function as well. + */ + var processAllClinitSectionsConcretely by getBooleanProperty(false) } /** diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/testcheckers/SettingsModificators.kt b/utbot-framework-api/src/main/kotlin/org/utbot/testcheckers/SettingsModificators.kt index 7b2223947b..ab468b11b3 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/testcheckers/SettingsModificators.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/testcheckers/SettingsModificators.kt @@ -109,6 +109,27 @@ inline fun withoutConcrete(block: () -> T): T { } } +inline fun withoutProcessingClinitSections(block: () -> T): T { + val prev = UtSettings.disableClinitSectionsAnalysis + UtSettings.disableClinitSectionsAnalysis = true + try { + return block() + } finally { + UtSettings.disableClinitSectionsAnalysis = prev + } +} + +inline fun withProcessingAllClinitSectionsConcretely(block: () -> T): T { + val prev = UtSettings.processAllClinitSectionsConcretely + UtSettings.processAllClinitSectionsConcretely = true + try { + return block() + } finally { + UtSettings.processAllClinitSectionsConcretely = prev + } +} + + /** * Run [block] with disabled sandbox in the concrete executor */ diff --git a/utbot-framework-test/src/test/kotlin/org/utbot/examples/objects/ClassForTestClinitSectionsTest.kt b/utbot-framework-test/src/test/kotlin/org/utbot/examples/objects/ClassForTestClinitSectionsTest.kt new file mode 100644 index 0000000000..3b68926413 --- /dev/null +++ b/utbot-framework-test/src/test/kotlin/org/utbot/examples/objects/ClassForTestClinitSectionsTest.kt @@ -0,0 +1,53 @@ +package org.utbot.examples.objects + +import org.junit.jupiter.api.Test +import org.utbot.testcheckers.eq +import org.utbot.testcheckers.withProcessingAllClinitSectionsConcretely +import org.utbot.testcheckers.withoutProcessingClinitSections +import org.utbot.testing.UtValueTestCaseChecker +import org.utbot.testing.atLeast + +internal class ClassForTestClinitSectionsTest : UtValueTestCaseChecker(testClass = ClassForTestClinitSections::class) { + @Test + fun testClinitWithoutClinitAnalysis() { + withoutProcessingClinitSections { + check( + ClassForTestClinitSections::resultDependingOnStaticSection, + eq(2) + ) + } + } + + @Test + fun testClinitWithClinitAnalysis() { + check( + ClassForTestClinitSections::resultDependingOnStaticSection, + eq(1), + coverage = atLeast(71) + ) + } + + @Test + fun testProcessConcretelyWithoutClinitAnalysis() { + withoutProcessingClinitSections { + withProcessingAllClinitSectionsConcretely { + check( + ClassForTestClinitSections::resultDependingOnStaticSection, + eq(2) + ) + } + } + } + + @Test + fun testProcessClinitConcretely() { + withProcessingAllClinitSectionsConcretely { + check( + ClassForTestClinitSections::resultDependingOnStaticSection, + eq(1), + coverage = atLeast(71) + ) + } + } +} + 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 8a6350006c..4ddd6b7865 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Traverser.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Traverser.kt @@ -487,6 +487,14 @@ class Traverser( return processStaticFieldConcretely(fieldRef, stmt) } + if (UtSettings.disableClinitSectionsAnalysis) { + return false + } + + if (UtSettings.processAllClinitSectionsConcretely) { + return processStaticFieldConcretely(fieldRef, stmt) + } + val field = fieldRef.field val declaringClass = field.declaringClass val declaringClassId = declaringClass.id diff --git a/utbot-sample/src/main/java/org/utbot/examples/objects/ClassForTestClinitSections.java b/utbot-sample/src/main/java/org/utbot/examples/objects/ClassForTestClinitSections.java new file mode 100644 index 0000000000..f037e88283 --- /dev/null +++ b/utbot-sample/src/main/java/org/utbot/examples/objects/ClassForTestClinitSections.java @@ -0,0 +1,13 @@ +package org.utbot.examples.objects; + +public class ClassForTestClinitSections { + private static int x = 5; + + public int resultDependingOnStaticSection() { + if (x == 5) { + return -1; + } + + return 1; + } +} From 9eeb77180d1e3be29d9ce08f1c5e1d89cf088ba2 Mon Sep 17 00:00:00 2001 From: Alexey Menshutin Date: Tue, 10 Jan 2023 11:09:07 +0800 Subject: [PATCH 2/3] Review fixes --- .../kotlin/org/utbot/framework/UtSettings.kt | 5 +- .../testcheckers/SettingsModificators.kt | 12 ++-- .../objects/ClassForTestClinitSectionsTest.kt | 61 ++++++++++++------- .../main/kotlin/org/utbot/engine/Traverser.kt | 7 ++- 4 files changed, 53 insertions(+), 32 deletions(-) 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 7b68eb7740..b0228f410e 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 @@ -510,12 +510,13 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS * Depending on this option, sections might be analyzed or not. * Note that some clinit sections still will be initialized using runtime information. */ - var disableClinitSectionsAnalysis by getBooleanProperty(false) + var enableClinitSectionsAnalysis by getBooleanProperty(true) /** * Process all clinit sections concretely. * - * If [disableClinitSectionsAnalysis] is true, it disables effect of this function as well. + * If [enableClinitSectionsAnalysis] is true, it disables effect of this option as well. + * Note that values processed concretely won't be replaced with unbounded symbolic variables. */ var processAllClinitSectionsConcretely by getBooleanProperty(false) } diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/testcheckers/SettingsModificators.kt b/utbot-framework-api/src/main/kotlin/org/utbot/testcheckers/SettingsModificators.kt index ab468b11b3..148eb95204 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/testcheckers/SettingsModificators.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/testcheckers/SettingsModificators.kt @@ -109,19 +109,19 @@ inline fun withoutConcrete(block: () -> T): T { } } -inline fun withoutProcessingClinitSections(block: () -> T): T { - val prev = UtSettings.disableClinitSectionsAnalysis - UtSettings.disableClinitSectionsAnalysis = true +inline fun withProcessingClinitSections(value: Boolean, block: () -> T): T { + val prev = UtSettings.enableClinitSectionsAnalysis + UtSettings.enableClinitSectionsAnalysis = value try { return block() } finally { - UtSettings.disableClinitSectionsAnalysis = prev + UtSettings.enableClinitSectionsAnalysis = prev } } -inline fun withProcessingAllClinitSectionsConcretely(block: () -> T): T { +inline fun withProcessingAllClinitSectionsConcretely(value: Boolean, block: () -> T): T { val prev = UtSettings.processAllClinitSectionsConcretely - UtSettings.processAllClinitSectionsConcretely = true + UtSettings.processAllClinitSectionsConcretely = value try { return block() } finally { diff --git a/utbot-framework-test/src/test/kotlin/org/utbot/examples/objects/ClassForTestClinitSectionsTest.kt b/utbot-framework-test/src/test/kotlin/org/utbot/examples/objects/ClassForTestClinitSectionsTest.kt index 3b68926413..2121db3aef 100644 --- a/utbot-framework-test/src/test/kotlin/org/utbot/examples/objects/ClassForTestClinitSectionsTest.kt +++ b/utbot-framework-test/src/test/kotlin/org/utbot/examples/objects/ClassForTestClinitSectionsTest.kt @@ -3,50 +3,65 @@ package org.utbot.examples.objects import org.junit.jupiter.api.Test import org.utbot.testcheckers.eq import org.utbot.testcheckers.withProcessingAllClinitSectionsConcretely -import org.utbot.testcheckers.withoutProcessingClinitSections +import org.utbot.testcheckers.withoutConcrete +import org.utbot.testcheckers.withProcessingClinitSections import org.utbot.testing.UtValueTestCaseChecker import org.utbot.testing.atLeast internal class ClassForTestClinitSectionsTest : UtValueTestCaseChecker(testClass = ClassForTestClinitSections::class) { @Test fun testClinitWithoutClinitAnalysis() { - withoutProcessingClinitSections { - check( - ClassForTestClinitSections::resultDependingOnStaticSection, - eq(2) - ) + withoutConcrete { + withProcessingClinitSections(value = false) { + check( + ClassForTestClinitSections::resultDependingOnStaticSection, + eq(2), + { r -> r == -1 }, + { r -> r == 1 } + ) + } } } @Test fun testClinitWithClinitAnalysis() { - check( - ClassForTestClinitSections::resultDependingOnStaticSection, - eq(1), - coverage = atLeast(71) - ) + withoutConcrete { + check( + ClassForTestClinitSections::resultDependingOnStaticSection, + eq(2), + { r -> r == -1 }, + { r -> r == 1 } + ) + } } @Test fun testProcessConcretelyWithoutClinitAnalysis() { - withoutProcessingClinitSections { - withProcessingAllClinitSectionsConcretely { - check( - ClassForTestClinitSections::resultDependingOnStaticSection, - eq(2) - ) + withoutConcrete { + withProcessingClinitSections(value = false) { + withProcessingAllClinitSectionsConcretely(value = true) { + check( + ClassForTestClinitSections::resultDependingOnStaticSection, + eq(2), + { r -> r == -1 }, + { r -> r == 1 } + ) + } } } } @Test fun testProcessClinitConcretely() { - withProcessingAllClinitSectionsConcretely { - check( - ClassForTestClinitSections::resultDependingOnStaticSection, - eq(1), - coverage = atLeast(71) - ) + withoutConcrete { + withProcessingAllClinitSectionsConcretely(value = true) { + check( + ClassForTestClinitSections::resultDependingOnStaticSection, + eq(1), + { r -> r == -1 }, + coverage = atLeast(71) + ) + } } } } 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 4ddd6b7865..e5c364d9f7 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Traverser.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Traverser.kt @@ -483,14 +483,19 @@ class Traverser( fieldRef: StaticFieldRef, stmt: Stmt ): Boolean { + // This order of processing options is important. + // First, we should process classes that + // cannot be analyzed without clinit sections, e.g., enums if (shouldProcessStaticFieldConcretely(fieldRef)) { return processStaticFieldConcretely(fieldRef, stmt) } - if (UtSettings.disableClinitSectionsAnalysis) { + // Then we should check if we should analyze clinit sections at all + if (!UtSettings.enableClinitSectionsAnalysis) { return false } + // Finally, we decide whether we should analyze clinit sections concretely or not if (UtSettings.processAllClinitSectionsConcretely) { return processStaticFieldConcretely(fieldRef, stmt) } From abbc13a07b8107b113ee13217fd29b186444d8a5 Mon Sep 17 00:00:00 2001 From: Alexey Menshutin Date: Tue, 10 Jan 2023 12:04:25 +0800 Subject: [PATCH 3/3] Update UtSettings.kt --- .../src/main/kotlin/org/utbot/framework/UtSettings.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b0228f410e..5dda9af68b 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 @@ -515,7 +515,7 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS /** * Process all clinit sections concretely. * - * If [enableClinitSectionsAnalysis] is true, it disables effect of this option as well. + * If [enableClinitSectionsAnalysis] is false, it disables effect of this option as well. * Note that values processed concretely won't be replaced with unbounded symbolic variables. */ var processAllClinitSectionsConcretely by getBooleanProperty(false)