diff --git a/settings.gradle b/settings.gradle index 4973300d4e..ac2c9d1279 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,4 +16,5 @@ include 'utbot-instrumentation-tests' include 'utbot-summary' include 'utbot-gradle' include 'utbot-maven' +include 'utbot-summary-tests' diff --git a/utbot-analytics/build.gradle b/utbot-analytics/build.gradle index 26c56fdcee..e6d06c3b18 100644 --- a/utbot-analytics/build.gradle +++ b/utbot-analytics/build.gradle @@ -5,7 +5,6 @@ configurations { mlmodels } - def osName = System.getProperty('os.name').toLowerCase().split()[0] if (osName == "mac") osName = "macosx" String classifier = osName + "-x86_64" @@ -49,11 +48,9 @@ dependencies { } test { - useJUnitPlatform { excludeTags 'Summary' } - } processResources { diff --git a/utbot-sample/src/main/java/guava/examples/math/Stats.java b/utbot-sample/src/main/java/guava/examples/math/Stats.java new file mode 100644 index 0000000000..a99a37fbda --- /dev/null +++ b/utbot-sample/src/main/java/guava/examples/math/Stats.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2012 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package guava.examples.math; + +import java.io.Serializable; +import java.util.Iterator; + + +public final class Stats implements Serializable { + + private final long count; + private final double mean; + private final double sumOfSquaresOfDeltas; + private final double min; + private final double max; + + /** + * Internal constructor. Users should use {@link #ofIterable} or {@link StatsAccumulator#snapshot}. + * + *

To ensure that the created instance obeys its contract, the parameters should satisfy the + * following constraints. This is the callers responsibility and is not enforced here. + * + *

+ */ + Stats(long count, double mean, double sumOfSquaresOfDeltas, double min, double max) { + this.count = count; + this.mean = mean; + this.sumOfSquaresOfDeltas = sumOfSquaresOfDeltas; + this.min = min; + this.max = max; + } + + /** + * Returns statistics over a dataset containing the given values. + * + * @param values a series of values, which will be converted to {@code double} values (this may + * cause loss of precision) + */ + public static Stats ofIterable(Iterable values) { + StatsAccumulator accumulator = new StatsAccumulator(); + accumulator.addAll(values); + return accumulator.snapshot(); + } + + /** + * Returns statistics over a dataset containing the given values. + * + * @param values a series of values, which will be converted to {@code double} values (this may + * cause loss of precision) + */ + public static Stats ofIterator(Iterator values) { + StatsAccumulator accumulator = new StatsAccumulator(); + accumulator.addAll(values); + return accumulator.snapshot(); + } + + /** + * Returns statistics over a dataset containing the given values. + * + * @param values a series of values + */ + public static Stats ofDoubles(double... values) { + StatsAccumulator acummulator = new StatsAccumulator(); + acummulator.addAll(values); + return acummulator.snapshot(); + } + + /** + * Returns statistics over a dataset containing the given values. + * + * @param values a series of values + */ + public static Stats ofInts(int... values) { + StatsAccumulator acummulator = new StatsAccumulator(); + acummulator.addAll(values); + return acummulator.snapshot(); + } + + /** + * Returns statistics over a dataset containing the given values. + * + * @param values a series of values, which will be converted to {@code double} values (this may + * cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15)) + */ + public static Stats ofLongs(long... values) { + StatsAccumulator acummulator = new StatsAccumulator(); + acummulator.addAll(values); + return acummulator.snapshot(); + } + + /** Returns the number of values. */ + public long count() { + return count; + } + + + private static final long serialVersionUID = 0; +} diff --git a/utbot-sample/src/main/java/guava/examples/math/StatsAccumulator.java b/utbot-sample/src/main/java/guava/examples/math/StatsAccumulator.java new file mode 100644 index 0000000000..57c9e93381 --- /dev/null +++ b/utbot-sample/src/main/java/guava/examples/math/StatsAccumulator.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2012 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package guava.examples.math; + +import java.util.Iterator; + +import static java.lang.Double.*; + +public final class StatsAccumulator { + + // These fields must satisfy the requirements of Stats' constructor as well as those of the stat + // methods of this class. + private long count = 0; + private double mean = 0.0; // any finite value will do, we only use it to multiply by zero for sum + private double sumOfSquaresOfDeltas = 0.0; + private double min = NaN; // any value will do + private double max = NaN; // any value will do + + /** Adds the given value to the dataset. */ + public void add(double value) { + if (count == 0) { + count = 1; + mean = value; + min = value; + max = value; + if (!isFinite(value)) { + sumOfSquaresOfDeltas = NaN; + } + } else { + count++; + if (isFinite(value) && isFinite(mean)) { + // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15) and (16) + double delta = value - mean; + mean += delta / count; + sumOfSquaresOfDeltas += delta * (value - mean); + } else { + mean = calculateNewMeanNonFinite(mean, value); + sumOfSquaresOfDeltas = NaN; + } + min = Math.min(min, value); + max = Math.max(max, value); + } + } + + /** + * Adds the given values to the dataset. + * + * @param values a series of values, which will be converted to {@code double} values (this may + * cause loss of precision) + */ + public void addAll(Iterable values) { + for (Number value : values) { + add(value.doubleValue()); + } + } + + /** + * Adds the given values to the dataset. + * + * @param values a series of values, which will be converted to {@code double} values (this may + * cause loss of precision) + */ + public void addAll(Iterator values) { + while (values.hasNext()) { + add(values.next().doubleValue()); + } + } + + /** + * Adds the given values to the dataset. + * + * @param values a series of values + */ + public void addAll(double... values) { + for (double value : values) { + add(value); + } + } + + /** + * Adds the given values to the dataset. + * + * @param values a series of values + */ + public void addAll(int... values) { + for (int value : values) { + add(value); + } + } + + /** + * Adds the given values to the dataset. + * + * @param values a series of values, which will be converted to {@code double} values (this may + * cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15)) + */ + public void addAll(long... values) { + for (long value : values) { + add(value); + } + } + + /** Returns an immutable snapshot of the current statistics. */ + public Stats snapshot() { + return new Stats(count, mean, sumOfSquaresOfDeltas, min, max); + } + + /** Returns the number of values. */ + public long count() { + return count; + } + + /** + * Calculates the new value for the accumulated mean when a value is added, in the case where at + * least one of the previous mean and the value is non-finite. + */ + static double calculateNewMeanNonFinite(double previousMean, double value) { + /* + * Desired behaviour is to match the results of applying the naive mean formula. In particular, + * the update formula can subtract infinities in cases where the naive formula would add them. + * + * Consequently: + * 1. If the previous mean is finite and the new value is non-finite then the new mean is that + * value (whether it is NaN or infinity). + * 2. If the new value is finite and the previous mean is non-finite then the mean is unchanged + * (whether it is NaN or infinity). + * 3. If both the previous mean and the new value are non-finite and... + * 3a. ...either or both is NaN (so mean != value) then the new mean is NaN. + * 3b. ...they are both the same infinities (so mean == value) then the mean is unchanged. + * 3c. ...they are different infinities (so mean != value) then the new mean is NaN. + */ + if (isFinite(previousMean)) { + // This is case 1. + return value; + } else if (isFinite(value) || previousMean == value) { + // This is case 2. or 3b. + return previousMean; + } else { + // This is case 3a. or 3c. + return NaN; + } + } + + public static boolean isFinite(double value) { + return NEGATIVE_INFINITY < value && value < POSITIVE_INFINITY; + } +} diff --git a/utbot-summary-tests/build.gradle b/utbot-summary-tests/build.gradle new file mode 100644 index 0000000000..cb460cbd1d --- /dev/null +++ b/utbot-summary-tests/build.gradle @@ -0,0 +1,17 @@ +apply from: "${parent.projectDir}/gradle/include/jvm-project.gradle" +apply plugin: "java" + +evaluationDependsOn(':utbot-framework') +compileTestJava.dependsOn tasks.getByPath(':utbot-framework:testClasses') + +dependencies { + implementation(project(":utbot-framework")) + implementation(project(':utbot-instrumentation')) + testImplementation project(':utbot-sample') + testImplementation group: 'junit', name: 'junit', version: junit4_version + testCompile project(':utbot-framework').sourceSets.test.output +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/SummaryTestCaseGeneratorTest.kt b/utbot-summary-tests/src/test/kotlin/examples/SummaryTestCaseGeneratorTest.kt similarity index 70% rename from utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/SummaryTestCaseGeneratorTest.kt rename to utbot-summary-tests/src/test/kotlin/examples/SummaryTestCaseGeneratorTest.kt index 1cdca4b148..443bee938e 100644 --- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/SummaryTestCaseGeneratorTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/SummaryTestCaseGeneratorTest.kt @@ -1,5 +1,6 @@ -package org.utbot.analytics.examples +package examples +import org.junit.jupiter.api.* import org.utbot.common.WorkaroundReason import org.utbot.common.workaround import org.utbot.examples.AbstractTestCaseGeneratorTest @@ -15,6 +16,7 @@ import org.utbot.framework.plugin.api.MockStrategyApi import org.utbot.framework.plugin.api.UtExecution import org.utbot.framework.plugin.api.UtMethod import org.utbot.framework.plugin.api.util.UtContext +import org.utbot.summary.comment.nextSynonyms import org.utbot.summary.summarize import kotlin.reflect.KClass import kotlin.reflect.KFunction @@ -22,15 +24,12 @@ import kotlin.reflect.KFunction1 import kotlin.reflect.KFunction2 import kotlin.reflect.KFunction3 import kotlin.reflect.KFunction4 -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Tag -@Tag("Summary") + +@Disabled open class SummaryTestCaseGeneratorTest( testClass: KClass<*>, - testCodeGeneration: Boolean = true, + testCodeGeneration: Boolean = false, languagePipelines: List = listOf( CodeGenerationLanguageLastStage(CodegenLanguage.JAVA), CodeGenerationLanguageLastStage(CodegenLanguage.KOTLIN, TestExecution) @@ -53,38 +52,43 @@ open class SummaryTestCaseGeneratorTest( coverage: CoverageMatcher = DoNotCalculate, mockStrategy: MockStrategyApi = MockStrategyApi.NO_MOCKS, summaryKeys: List, + methodNames: List = listOf(), displayNames: List = listOf() - ) = check(method, mockStrategy, coverage, summaryKeys, displayNames) + ) = check(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) protected inline fun checkOneArgument( method: KFunction2<*, T, R>, coverage: CoverageMatcher = DoNotCalculate, mockStrategy: MockStrategyApi = MockStrategyApi.NO_MOCKS, summaryKeys: List, + methodNames: List = listOf(), displayNames: List = listOf() - ) = check(method, mockStrategy, coverage, summaryKeys, displayNames) + ) = check(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) protected inline fun checkTwoArguments( method: KFunction3<*, T1, T2, R>, coverage: CoverageMatcher = DoNotCalculate, mockStrategy: MockStrategyApi = MockStrategyApi.NO_MOCKS, summaryKeys: List, + methodNames: List = listOf(), displayNames: List = listOf() - ) = check(method, mockStrategy, coverage, summaryKeys, displayNames) + ) = check(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) protected inline fun checkThreeArguments( method: KFunction4<*, T1, T2, T3, R>, coverage: CoverageMatcher = DoNotCalculate, mockStrategy: MockStrategyApi = MockStrategyApi.NO_MOCKS, summaryKeys: List, + methodNames: List = listOf(), displayNames: List = listOf() - ) = check(method, mockStrategy, coverage, summaryKeys, displayNames) + ) = check(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) inline fun check( method: KFunction, mockStrategy: MockStrategyApi, coverageMatcher: CoverageMatcher, summaryKeys: List, + methodNames: List, displayNames: List ) { workaround(WorkaroundReason.HACK) { @@ -98,9 +102,24 @@ open class SummaryTestCaseGeneratorTest( val testCase = executionsModel(utMethod, mockStrategy) testCase.summarize(searchDirectory) testCase.executions.checkMatchersWithTextSummary(summaryKeys) + testCase.executions.checkMatchersWithMethodNames(methodNames) testCase.executions.checkMatchersWithDisplayNames(displayNames) } + /** + * It removes from the String all whitespaces, tabs etc. + * + * @see Explanation of the used regular expression. + */ + private fun String.normalize(): String { + var result = this.replace("\\s+".toRegex(), "") + nextSynonyms.forEach { + result = result.replace(it, "") + } + return result + } + + fun List.checkMatchersWithTextSummary( summaryTextKeys: List, ) { @@ -108,9 +127,22 @@ open class SummaryTestCaseGeneratorTest( return } val notMatchedExecutions = this.filter { execution -> - summaryTextKeys.none { summaryKey -> execution.summary?.contains(summaryKey) == true } + summaryTextKeys.none { summaryKey -> val normalize = execution.summary?.toString()?.normalize() + normalize?.contains(summaryKey.normalize()) == true } + } + Assertions.assertTrue(notMatchedExecutions.isEmpty()) { "Not matched comments ${summaries(notMatchedExecutions)}" } + } + + fun List.checkMatchersWithMethodNames( + methodNames: List, + ) { + if (methodNames.isEmpty()) { + return + } + val notMatchedExecutions = this.filter { execution -> + methodNames.none { methodName -> execution.testMethodName?.equals(methodName) == true } } - Assertions.assertTrue(notMatchedExecutions.isEmpty()) { "Not matched summaries ${summaries(notMatchedExecutions)}" } + Assertions.assertTrue(notMatchedExecutions.isEmpty()) { "Not matched display names ${summaries(notMatchedExecutions)}" } } fun List.checkMatchersWithDisplayNames( @@ -122,7 +154,7 @@ open class SummaryTestCaseGeneratorTest( val notMatchedExecutions = this.filter { execution -> displayNames.none { displayName -> execution.displayName?.equals(displayName) == true } } - Assertions.assertTrue(notMatchedExecutions.isEmpty()) { "Not matched summaries ${summaries(notMatchedExecutions)}" } + Assertions.assertTrue(notMatchedExecutions.isEmpty()) { "Not matched display names ${summaries(notMatchedExecutions)}" } } private fun summaries(executions: List): String { @@ -132,5 +164,4 @@ open class SummaryTestCaseGeneratorTest( } return result } - } \ No newline at end of file diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/algorithms/SummaryReturnExampleTest.kt b/utbot-summary-tests/src/test/kotlin/examples/algorithms/SummaryReturnExampleTest.kt similarity index 98% rename from utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/algorithms/SummaryReturnExampleTest.kt rename to utbot-summary-tests/src/test/kotlin/examples/algorithms/SummaryReturnExampleTest.kt index 7d5e23e262..e2e5181004 100644 --- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/algorithms/SummaryReturnExampleTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/algorithms/SummaryReturnExampleTest.kt @@ -1,9 +1,12 @@ -package org.utbot.analytics.examples.algorithms +package examples.algorithms -import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest +import examples.SummaryTestCaseGeneratorTest +import org.junit.Ignore +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Tag import org.utbot.examples.algorithms.ReturnExample import org.junit.jupiter.api.Test - +@Disabled class SummaryReturnExampleTest : SummaryTestCaseGeneratorTest( ReturnExample::class, ) { diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/controlflow/SummaryCycleTest.kt b/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummaryCycleTest.kt similarity index 95% rename from utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/controlflow/SummaryCycleTest.kt rename to utbot-summary-tests/src/test/kotlin/examples/controlflow/SummaryCycleTest.kt index f5e655d102..80a7f05ba6 100644 --- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/controlflow/SummaryCycleTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummaryCycleTest.kt @@ -1,9 +1,12 @@ -package org.utbot.analytics.examples.controlflow +package examples.controlflow -import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest +import examples.SummaryTestCaseGeneratorTest +import org.junit.Ignore +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Tag import org.utbot.examples.controlflow.Cycles import org.junit.jupiter.api.Test - +@Disabled class SummaryCycleTest : SummaryTestCaseGeneratorTest( Cycles::class, ) { diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryInnerCallsTest.kt b/utbot-summary-tests/src/test/kotlin/examples/inner/SummaryInnerCallsTest.kt similarity index 99% rename from utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryInnerCallsTest.kt rename to utbot-summary-tests/src/test/kotlin/examples/inner/SummaryInnerCallsTest.kt index 976f3d969e..19d077b972 100644 --- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryInnerCallsTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/inner/SummaryInnerCallsTest.kt @@ -1,9 +1,13 @@ -package org.utbot.analytics.examples.inner +package examples.inner -import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest +import examples.SummaryTestCaseGeneratorTest +import org.junit.Ignore +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Tag import org.utbot.examples.inner.InnerCalls import org.junit.jupiter.api.Test +@Disabled class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( InnerCalls::class, ) { diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryNestedCallsTest.kt b/utbot-summary-tests/src/test/kotlin/examples/inner/SummaryNestedCallsTest.kt similarity index 90% rename from utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryNestedCallsTest.kt rename to utbot-summary-tests/src/test/kotlin/examples/inner/SummaryNestedCallsTest.kt index 3e831c2e9e..e6e0eaa820 100644 --- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryNestedCallsTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/inner/SummaryNestedCallsTest.kt @@ -1,9 +1,12 @@ -package org.utbot.analytics.examples.inner +package examples.inner -import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest +import examples.SummaryTestCaseGeneratorTest +import org.junit.Ignore +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Tag import org.utbot.examples.inner.NestedCalls import org.junit.jupiter.api.Test - +@Disabled class SummaryNestedCallsTest : SummaryTestCaseGeneratorTest( NestedCalls::class, ) { diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/ternary/SummaryTernary.kt b/utbot-summary-tests/src/test/kotlin/examples/ternary/SummaryTernary.kt similarity index 98% rename from utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/ternary/SummaryTernary.kt rename to utbot-summary-tests/src/test/kotlin/examples/ternary/SummaryTernary.kt index 8d3571feb1..f5a3bfc4db 100644 --- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/ternary/SummaryTernary.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/ternary/SummaryTernary.kt @@ -1,10 +1,13 @@ -package org.utbot.analytics.examples.ternary +package examples.ternary -import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest +import examples.SummaryTestCaseGeneratorTest +import org.junit.Ignore +import org.junit.jupiter.api.Disabled import org.utbot.examples.ternary.Ternary import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test +@Disabled class SummaryTernary : SummaryTestCaseGeneratorTest( Ternary::class, ) { diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/guava/math/SummaryIntMath.kt b/utbot-summary-tests/src/test/kotlin/math/SummaryIntMath.kt similarity index 97% rename from utbot-analytics/src/test/kotlin/org/utbot/analytics/guava/math/SummaryIntMath.kt rename to utbot-summary-tests/src/test/kotlin/math/SummaryIntMath.kt index d92c84f9d3..37e4ad24ee 100644 --- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/guava/math/SummaryIntMath.kt +++ b/utbot-summary-tests/src/test/kotlin/math/SummaryIntMath.kt @@ -1,9 +1,12 @@ -package org.utbot.analytics.guava.math +package math -import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest +import examples.SummaryTestCaseGeneratorTest import guava.examples.math.IntMath +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test +@Disabled class SummaryIntMath : SummaryTestCaseGeneratorTest( IntMath::class, ) { diff --git a/utbot-summary-tests/src/test/kotlin/math/SummaryOfMath.kt b/utbot-summary-tests/src/test/kotlin/math/SummaryOfMath.kt new file mode 100644 index 0000000000..22260a231c --- /dev/null +++ b/utbot-summary-tests/src/test/kotlin/math/SummaryOfMath.kt @@ -0,0 +1,79 @@ +package math + +import examples.SummaryTestCaseGeneratorTest +import guava.examples.math.Stats +import org.junit.jupiter.api.Test +import org.utbot.examples.DoNotCalculate +import org.utbot.framework.plugin.api.MockStrategyApi + +/** + * It runs test generation for the poor analogue of the Stats.of method ported from the guava-26.0 framework + * and validates generated docs, display names and test method names. + * + * @see Related issue + */ +class SummaryOfMath : SummaryTestCaseGeneratorTest( + Stats::class, +) { + @Test + fun testOfInts() { + val summary1 = "Test calls StatsAccumulator::addAll,\n" + + " there it triggers recursion of addAll once, \n" + + "Test throws NullPointerException in: acummulator.addAll(values);\n" + val summary2 = "Test calls StatsAccumulator::addAll,\n" + + " there it does not iterate for(int value: values), \n" + + "Test later calls StatsAccumulator::snapshot,\n" + + " there it returns from: return new Stats(count, mean, sumOfSquaresOfDeltas, min, max);\n" + + " \n" + + "Test then returns from: return acummulator.snapshot();" + val summary3 = "Test calls StatsAccumulator::addAll,\n" + + " there it iterates the loop for(int value: values) once. \n" + + "Test later calls StatsAccumulator::snapshot,\n" + + " there it returns from: return new Stats(count, mean, sumOfSquaresOfDeltas, min, max);\n" + + " \n" + + "Test then returns from: return acummulator.snapshot();" + val summary4 = "Test calls StatsAccumulator::addAll,\n" + + " there it iterates the loop for(int value: values) twice. \n" + + "Test later calls StatsAccumulator::snapshot,\n" + + " there it returns from: return new Stats(count, mean, sumOfSquaresOfDeltas, min, max);\n" + + " \n" + + "Test later returns from: return acummulator.snapshot();\n" + + val methodName1 = "testOfInts_StatsAccumulatorAddAll" + val methodName2 = "testOfInts_snapshot" + val methodName3 = "testOfInts_IterateForEachLoop" + val methodName4 = "testOfInts_IterateForEachLoop_1" + + val displayName1 = "acummulator.addAll(values) : True -> ThrowNullPointerException" + val displayName2 = "snapshot -> return new Stats(count, mean, sumOfSquaresOfDeltas, min, max)" + val displayName3 = "addAll -> return new Stats(count, mean, sumOfSquaresOfDeltas, min, max)" + val displayName4 = "addAll -> return new Stats(count, mean, sumOfSquaresOfDeltas, min, max)" + + val method = Stats::ofInts + val mockStrategy = MockStrategyApi.NO_MOCKS + val coverage = DoNotCalculate + + val summaryKeys = listOf( + summary1, + summary2, + summary3, + summary4 + ) + + val displayNames = listOf( + displayName1, + displayName2, + displayName3, + displayName4 + ) + + val methodNames = listOf( + methodName1, + methodName2, + methodName3, + methodName4 + ) + + check(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) + } +} \ No newline at end of file diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/ast/JimpleToASTMap.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/ast/JimpleToASTMap.kt index 3a4c048e85..13b0ed1673 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/ast/JimpleToASTMap.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/ast/JimpleToASTMap.kt @@ -61,7 +61,8 @@ class JimpleToASTMap(stmts: Iterable, methodDeclaration: MethodDeclaration if (ASTNode != null) { if (ASTNode is IfStmt && stmt is JIfStmt) { - ASTNode = ifStmtToNodeMap[ASTNode]?.remove() + val nodes = ifStmtToNodeMap[ASTNode] + if(!nodes.isNullOrEmpty()) ASTNode = nodes.remove() } else if (stmt is JReturnStmt) { ASTNode = validateReturnASTNode(ASTNode) }