diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt index d552d32c14..43077551f2 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt @@ -393,7 +393,7 @@ class UtBotSymbolicEngine( applicationContext.getBeansAssignableTo(methodUnderTest.classId).isEmpty()) { val fullConfigDisplayName = (applicationContext.springSettings as? SpringSettings.PresentSpringSettings) ?.configuration?.fullDisplayName - val errorDescription = "No beans of type ${methodUnderTest.classId.name} are found. " + + val errorDescription = "No beans of type ${methodUnderTest.classId.name} were found. " + "Try choosing different Spring configuration or adding beans to $fullConfigDisplayName" emit(UtError( errorDescription, diff --git a/utbot-sample/src/main/java/org/utbot/examples/controlflow/Conditions.java b/utbot-sample/src/main/java/org/utbot/examples/controlflow/Conditions.java index 13539a98db..d13d9d6282 100644 --- a/utbot-sample/src/main/java/org/utbot/examples/controlflow/Conditions.java +++ b/utbot-sample/src/main/java/org/utbot/examples/controlflow/Conditions.java @@ -31,4 +31,10 @@ public void emptyBranches(boolean condition) { // do nothing } } + + public int elseIf(int id) throws RuntimeException { + if (id > 0) return 0; + else if (id == 0) throw new RuntimeException("Exception message"); + else return 1; + } } diff --git a/utbot-sample/src/main/java/org/utbot/examples/controlflow/Switch.java b/utbot-sample/src/main/java/org/utbot/examples/controlflow/Switch.java index be921cd1b4..63f9f0b8f5 100644 --- a/utbot-sample/src/main/java/org/utbot/examples/controlflow/Switch.java +++ b/utbot-sample/src/main/java/org/utbot/examples/controlflow/Switch.java @@ -59,6 +59,19 @@ public int charToIntSwitch(char c) { } } + public int throwExceptionInSwitchArgument() { + switch (getChar()) { + case 'I': + return 1; + default: + return 100; + } + } + + private char getChar() throws RuntimeException { + throw new RuntimeException("Exception message"); + } + //TODO: String switch // public int stringSwitch(String s) { // switch (s) { @@ -72,4 +85,3 @@ public int charToIntSwitch(char c) { // } // } } - diff --git a/utbot-sample/src/main/java/org/utbot/examples/exceptions/ExceptionExamples.java b/utbot-sample/src/main/java/org/utbot/examples/exceptions/ExceptionExamples.java index 36f7bef2f9..efc9e9eca1 100644 --- a/utbot-sample/src/main/java/org/utbot/examples/exceptions/ExceptionExamples.java +++ b/utbot-sample/src/main/java/org/utbot/examples/exceptions/ExceptionExamples.java @@ -123,4 +123,8 @@ private int nestedWithThrow(int i) { } return i; } -} \ No newline at end of file + + public int throwExceptionInMethodUnderTest() throws RuntimeException { + throw new RuntimeException("Exception message"); + } +} diff --git a/utbot-summary-tests/src/test/kotlin/examples/algorithms/SummaryBinarySearchTest.kt b/utbot-summary-tests/src/test/kotlin/examples/algorithms/SummaryBinarySearchTest.kt index 3714717fcd..a9175c1b9c 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/algorithms/SummaryBinarySearchTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/algorithms/SummaryBinarySearchTest.kt @@ -37,19 +37,19 @@ class SummaryBinarySearchTest : SummaryTestCaseGeneratorTest( "returns from: return right + 1;\n" val summary5 = "Test invokes:\n" + " org.utbot.examples.algorithms.BinarySearch#isUnsorted(long[]) once\n" + - "throws NullPointerException in: isUnsorted(array)\n" + "throws NullPointerException when: isUnsorted(array)\n" val summary6 = "Test invokes:\n" + " org.utbot.examples.algorithms.BinarySearch#isUnsorted(long[]) once\n" + "executes conditions:\n" + " (isUnsorted(array)): True\n" + - "throws IllegalArgumentException after condition: isUnsorted(array)\n" + "throws IllegalArgumentException when: isUnsorted(array)\n" val methodName1 = "testLeftBinSearch_NotFound" val methodName2 = "testLeftBinSearch_MiddleOfArrayLessThanKey" val methodName3 = "testLeftBinSearch_Found" val methodName4 = "testLeftBinSearch_Found_1" - val methodName5 = "testLeftBinSearch_BinarySearchIsUnsorted" - val methodName6 = "testLeftBinSearch_IsUnsorted" + val methodName5 = "testLeftBinSearch_ThrowNullPointerException" + val methodName6 = "testLeftBinSearch_ThrowIllegalArgumentException" val displayName1 = "found : False -> return -1" val displayName2 = "array[middle] == key : False -> return -1" diff --git a/utbot-summary-tests/src/test/kotlin/examples/algorithms/SummarySortTest.kt b/utbot-summary-tests/src/test/kotlin/examples/algorithms/SummarySortTest.kt index b1bb8f9879..416c868587 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/algorithms/SummarySortTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/algorithms/SummarySortTest.kt @@ -12,10 +12,10 @@ class SummarySortTest : SummaryTestCaseGeneratorTest( @Test fun testDefaultSort() { val summary1 = "Test \n" + - "throws NullPointerException in: array.length < 4\n" + "throws NullPointerException when: array.length < 4\n" val summary2 = "Test executes conditions:\n" + " (array.length < 4): True\n" + - "throws IllegalArgumentException after condition: array.length < 4\n" + "throws IllegalArgumentException when: array.length < 4\n" val summary3 = "Test executes conditions:\n" + " (array.length < 4): False\n" + "invokes:\n" + @@ -23,7 +23,7 @@ class SummarySortTest : SummaryTestCaseGeneratorTest( "returns from: return array;\n" val methodName1 = "testDefaultSort_ThrowNullPointerException" - val methodName2 = "testDefaultSort_ArrayLengthLessThan4" + val methodName2 = "testDefaultSort_ThrowIllegalArgumentException" val methodName3 = "testDefaultSort_ArrayLengthGreaterOrEqual4" val displayName1 = "array.length < 4 -> ThrowNullPointerException" diff --git a/utbot-summary-tests/src/test/kotlin/examples/collections/SummaryListWrapperReturnsVoidTest.kt b/utbot-summary-tests/src/test/kotlin/examples/collections/SummaryListWrapperReturnsVoidTest.kt index 820a7904fe..e95a5940f4 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/collections/SummaryListWrapperReturnsVoidTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/collections/SummaryListWrapperReturnsVoidTest.kt @@ -26,7 +26,7 @@ class SummaryListWrapperReturnsVoidTest : SummaryTestCaseGeneratorTest( val summary3 = "Test returns from: return i[0];" val summary4 = "Test returns from: return i[0];" - val methodName1 = "testRunForEach_ListForEach" + val methodName1 = "testRunForEach_ThrowNullPointerException" val methodName2 = "testRunForEach_Return0OfI" val methodName3 = "testRunForEach_Return0OfI_1" val methodName4 = "testRunForEach_Return0OfI_2" @@ -88,7 +88,7 @@ class SummaryListWrapperReturnsVoidTest : SummaryTestCaseGeneratorTest( "returns from: return sum[0];" val methodName1 = "testSumPositiveForEach_ThrowNullPointerException" - val methodName2 = "testSumPositiveForEach_ListForEach" + val methodName2 = "testSumPositiveForEach_ThrowNullPointerException_1" val methodName3 = "testSumPositiveForEach_0OfSumEqualsZero" val methodName4 = "testSumPositiveForEach_0OfSumEqualsZero_1" val methodName5 = "testSumPositiveForEach_0OfSumNotEqualsZero" diff --git a/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummaryConditionsTest.kt b/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummaryConditionsTest.kt index a92a64190f..39f854f67e 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummaryConditionsTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummaryConditionsTest.kt @@ -96,4 +96,56 @@ class SummaryConditionsTest : SummaryTestCaseGeneratorTest( summaryCheck(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) } -} \ No newline at end of file + + @Test + fun testElseIf() { + val summary1 = "@utbot.classUnderTest {@link Conditions}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Conditions#elseIf(int)}\n" + + "@utbot.executesCondition {@code (id > 0): True}\n" + + "@utbot.returnsFrom {@code return 0;}" + + val summary2 = "@utbot.classUnderTest {@link Conditions}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Conditions#elseIf(int)}\n" + + "@utbot.executesCondition {@code (id > 0): False}\n" + + "@utbot.executesCondition {@code (id == 0): False}\n" + + "@utbot.returnsFrom {@code return 1;}" + + val summary3 = "@utbot.classUnderTest {@link Conditions}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Conditions#elseIf(int)}\n" + + "@utbot.executesCondition {@code (id > 0): False}\n" + + "@utbot.executesCondition {@code (id == 0): True}\n" + + "@utbot.throwsException {@link java.lang.RuntimeException} when: id == 0" + + val methodName1 = "testElseIf_IdGreaterThanZero" + val methodName2 = "testElseIf_IdNotEqualsZero" + val methodName3 = "testElseIf_ThrowRuntimeException" + + val displayName1 = "id > 0 : True -> id > 0" + val displayName2 = "id > 0 : False -> return 1" + val displayName3 = "id == 0 -> ThrowRuntimeException" + + val summaryKeys = listOf( + summary1, + summary2, + summary3 + ) + + val displayNames = listOf( + displayName1, + displayName2, + displayName3 + ) + + val methodNames = listOf( + methodName1, + methodName2, + methodName3 + ) + + val method = Conditions::elseIf + val mockStrategy = MockStrategyApi.NO_MOCKS + val coverage = DoNotCalculate + + summaryCheck(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) + } +} diff --git a/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummarySwitchTest.kt b/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummarySwitchTest.kt index 0b94b30b25..8b2730593e 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummarySwitchTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummarySwitchTest.kt @@ -5,6 +5,7 @@ import examples.SummaryTestCaseGeneratorTest import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.utbot.examples.controlflow.Switch +import org.utbot.examples.exceptions.ExceptionExamples import org.utbot.framework.plugin.api.MockStrategyApi import org.utbot.testing.DoNotCalculate @@ -16,19 +17,19 @@ class SummarySwitchTest : SummaryTestCaseGeneratorTest( fun testSimpleSwitch() { val summary1 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#simpleSwitch(int)}\n" + - "@utbot.activatesSwitch {@code case 10}\n" + + "@utbot.activatesSwitch {@code switch(x) case: 10}\n" + "@utbot.returnsFrom {@code return 10;}" val summary2 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#simpleSwitch(int)}\n" + - "@utbot.activatesSwitch {@code case default}\n" + + "@utbot.activatesSwitch {@code switch(x) case: default}\n" + "@utbot.returnsFrom {@code return -1;}" val summary3 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#simpleSwitch(int)}\n" + - "@utbot.activatesSwitch {@code case 12}\n" + + "@utbot.activatesSwitch {@code switch(x) case: 12}\n" + "@utbot.returnsFrom {@code return 12;}" val summary4 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#simpleSwitch(int)}\n" + - "@utbot.activatesSwitch {@code case 13}\n" + + "@utbot.activatesSwitch {@code switch(x) case: 13}\n" + "@utbot.returnsFrom {@code return 13;}" val methodName1 = "testSimpleSwitch_Return10" @@ -37,7 +38,7 @@ class SummarySwitchTest : SummaryTestCaseGeneratorTest( val methodName4 = "testSimpleSwitch_Return13" val displayName1 = "switch(x) case: 10 -> return 10" - val displayName2 = "switch(x) case: Default -> return -1" + val displayName2 = "switch(x) case: default -> return -1" val displayName3 = "switch(x) case: 12 -> return 12" val displayName4 = "switch(x) case: 13 -> return 13" @@ -73,40 +74,39 @@ class SummarySwitchTest : SummaryTestCaseGeneratorTest( fun testCharToIntSwitch() { val summary1 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#charToIntSwitch(char)}\n" + - "@utbot.activatesSwitch {@code case 'C'}\n" + + "@utbot.activatesSwitch {@code switch(c) case: 'C'}\n" + "@utbot.returnsFrom {@code return 100;}\n" val summary2 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#charToIntSwitch(char)}\n" + - "@utbot.activatesSwitch {@code case 'V'}\n" + + "@utbot.activatesSwitch {@code switch(c) case: 'V'}\n" + "@utbot.returnsFrom {@code return 5;}\n" val summary3 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#charToIntSwitch(char)}\n" + - "@utbot.activatesSwitch {@code case 'I'}\n" + + "@utbot.activatesSwitch {@code switch(c) case: 'I'}\n" + "@utbot.returnsFrom {@code return 1;}\n" val summary4 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#charToIntSwitch(char)}\n" + - "@utbot.activatesSwitch {@code case 'X'}\n" + + "@utbot.activatesSwitch {@code switch(c) case: 'X'}\n" + "@utbot.returnsFrom {@code return 10;}\n" val summary5 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#charToIntSwitch(char)}\n" + - "@utbot.activatesSwitch {@code case 'M'}\n" + + "@utbot.activatesSwitch {@code switch(c) case: 'M'}\n" + "@utbot.returnsFrom {@code return 1000;}\n" val summary6 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#charToIntSwitch(char)}\n" + - "@utbot.activatesSwitch {@code case 'D'}\n" + + "@utbot.activatesSwitch {@code switch(c) case: 'D'}\n" + "@utbot.returnsFrom {@code return 500;}\n" val summary7 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#charToIntSwitch(char)}\n" + - "@utbot.activatesSwitch {@code case 'L'}\n" + + "@utbot.activatesSwitch {@code switch(c) case: 'L'}\n" + "@utbot.returnsFrom {@code return 50;}\n" val summary8 = "@utbot.classUnderTest {@link Switch}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#charToIntSwitch(char)}\n" + "@utbot.invokes {@link java.lang.StringBuilder#append(java.lang.String)}\n" + "@utbot.invokes {@link java.lang.StringBuilder#append(char)}\n" + "@utbot.invokes {@link java.lang.StringBuilder#toString()}\n" + - "@utbot.activatesSwitch {@code case default}\n" + - "@utbot.throwsException {@link java.lang.IllegalArgumentException} in: default:\n" + - " throw new IllegalArgumentException(\"Unrecognized symbol: \" + c);\n" + "@utbot.activatesSwitch {@code switch(c) case: default}\n" + + "@utbot.throwsException {@link java.lang.IllegalArgumentException} when: switch(c) case: default\n" val methodName1 = "testCharToIntSwitch_Return100" val methodName2 = "testCharToIntSwitch_Return5" @@ -115,7 +115,7 @@ class SummarySwitchTest : SummaryTestCaseGeneratorTest( val methodName5 = "testCharToIntSwitch_Return1000" val methodName6 = "testCharToIntSwitch_Return500" val methodName7 = "testCharToIntSwitch_Return50" - val methodName8 = "testCharToIntSwitch_StringBuilderToString" + val methodName8 = "testCharToIntSwitch_ThrowIllegalArgumentException" val displayName1 = "switch(c) case: 'C' -> return 100" val displayName2 = "switch(c) case: 'V' -> return 5" @@ -124,7 +124,7 @@ class SummarySwitchTest : SummaryTestCaseGeneratorTest( val displayName5 = "switch(c) case: 'M' -> return 1000" val displayName6 = "switch(c) case: 'D' -> return 500" val displayName7 = "switch(c) case: 'L' -> return 50" - val displayName8 = """default: throw new IllegalArgumentException("Unrecognized symbol: " + c) -> ThrowIllegalArgumentException""" + val displayName8 = "switch(c) case: default -> ThrowIllegalArgumentException" val summaryKeys = listOf( summary1, @@ -165,4 +165,34 @@ class SummarySwitchTest : SummaryTestCaseGeneratorTest( summaryCheck(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) } -} \ No newline at end of file + + @Test + fun testThrowExceptionInSwitchArgument() { + val summary1 = "@utbot.classUnderTest {@link Switch}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.controlflow.Switch#throwExceptionInSwitchArgument()}\n" + + "@utbot.invokes org.utbot.examples.controlflow.Switch#getChar()\n" + + "@utbot.throwsException {@link java.lang.RuntimeException} in: switch(getChar())\n" + + val methodName1 = "testThrowExceptionInSwitchArgument_ThrowRuntimeException" + + val displayName1 = "switch(getChar()) -> ThrowRuntimeException" + + val summaryKeys = listOf( + summary1, + ) + + val displayNames = listOf( + displayName1, + ) + + val methodNames = listOf( + methodName1, + ) + + val method = Switch::throwExceptionInSwitchArgument + val mockStrategy = MockStrategyApi.NO_MOCKS + val coverage = DoNotCalculate + + summaryCheck(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) + } +} diff --git a/utbot-summary-tests/src/test/kotlin/examples/exceptions/SummaryExceptionClusteringExamplesTest.kt b/utbot-summary-tests/src/test/kotlin/examples/exceptions/SummaryExceptionClusteringExamplesTest.kt index 4ad6bfc6ff..3751f75dd0 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/exceptions/SummaryExceptionClusteringExamplesTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/exceptions/SummaryExceptionClusteringExamplesTest.kt @@ -23,13 +23,13 @@ class SummaryExceptionClusteringExamplesTest : SummaryTestCaseGeneratorTest( "@utbot.methodUnderTest {@link org.utbot.examples.exceptions.ExceptionClusteringExamples#differentExceptions(int)}\n" + "@utbot.executesCondition {@code (i == 0): False}\n" + "@utbot.executesCondition {@code (i == 1): True}\n" + - "@utbot.throwsException {@link org.utbot.examples.exceptions.MyCheckedException} after condition: i == 1" + "@utbot.throwsException {@link org.utbot.examples.exceptions.MyCheckedException} when: i == 1" val summary3 = "@utbot.classUnderTest {@link ExceptionClusteringExamples}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.exceptions.ExceptionClusteringExamples#differentExceptions(int)}\n" + "@utbot.executesCondition {@code (i == 0): False}\n" + "@utbot.executesCondition {@code (i == 1): False}\n" + "@utbot.executesCondition {@code (i == 2): True}\n" + - "@utbot.throwsException {@link java.lang.IllegalArgumentException} after condition: i == 2" + "@utbot.throwsException {@link java.lang.IllegalArgumentException} when: i == 2" val summary4 = "@utbot.classUnderTest {@link ExceptionClusteringExamples}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.exceptions.ExceptionClusteringExamples#differentExceptions(int)}\n" + "@utbot.executesCondition {@code (i == 0): False}\n" + @@ -37,9 +37,9 @@ class SummaryExceptionClusteringExamplesTest : SummaryTestCaseGeneratorTest( "@utbot.executesCondition {@code (i == 2): False}\n" + "@utbot.returnsFrom {@code return i * 2;}\n" - val methodName1 = "testDifferentExceptions_IEqualsZero" - val methodName2 = "testDifferentExceptions_IEquals1" - val methodName3 = "testDifferentExceptions_IEquals2" + val methodName1 = "testDifferentExceptions_ThrowArithmeticException" + val methodName2 = "testDifferentExceptions_ThrowMyCheckedException" + val methodName3 = "testDifferentExceptions_ThrowIllegalArgumentException" val methodName4 = "testDifferentExceptions_INotEquals2" val displayName1 = "return 100 / i : True -> ThrowArithmeticException" diff --git a/utbot-summary-tests/src/test/kotlin/examples/exceptions/SummaryExceptionExampleTest.kt b/utbot-summary-tests/src/test/kotlin/examples/exceptions/SummaryExceptionExampleTest.kt index 6a252b5363..8d054cfdce 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/exceptions/SummaryExceptionExampleTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/exceptions/SummaryExceptionExampleTest.kt @@ -97,4 +97,33 @@ class SummaryExceptionExampleTest : SummaryTestCaseGeneratorTest( summaryCheck(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) } + + @Test + fun testThrowExceptionInMethodUnderTest() { + val summary1 = "@utbot.classUnderTest {@link ExceptionExamples}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.exceptions.ExceptionExamples#throwExceptionInMethodUnderTest()}\n" + + "@utbot.throwsException {@link java.lang.RuntimeException} in: throw new RuntimeException(\"Exception message\");\n" + + val methodName1 = "testThrowExceptionInMethodUnderTest_ThrowRuntimeException" + + val displayName1 = " -> ThrowRuntimeException" + + val summaryKeys = listOf( + summary1, + ) + + val displayNames = listOf( + displayName1, + ) + + val methodNames = listOf( + methodName1, + ) + + val method = ExceptionExamples::throwExceptionInMethodUnderTest + val mockStrategy = MockStrategyApi.NO_MOCKS + val coverage = DoNotCalculate + + summaryCheck(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) + } } \ No newline at end of file diff --git a/utbot-summary-tests/src/test/kotlin/examples/inner/SummaryInnerCallsTest.kt b/utbot-summary-tests/src/test/kotlin/examples/inner/SummaryInnerCallsTest.kt index f992dd73b1..b6072aa076 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/inner/SummaryInnerCallsTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/inner/SummaryInnerCallsTest.kt @@ -146,7 +146,7 @@ class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( val methodName4 = "testCallLeftBinSearch_Found" val methodName5 = "testCallLeftBinSearch_ThrowIllegalArgumentException" val methodName6 = "testCallLeftBinSearch_ThrowIllegalArgumentException_1" - val methodName7 = "testCallLeftBinSearch_BinarySearchIsUnsorted" + val methodName7 = "testCallLeftBinSearch_ThrowNullPointerException" val displayName1 = "found : False -> return -1" @@ -327,9 +327,9 @@ class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( " triggers recursion of factorial once, \n" + "Test throws IllegalArgumentException in: return r.factorial(n);\n" - val methodName1 = "testCallFactorial_NEqualsZero" + val methodName1 = "testCallFactorial_ThrowIllegalArgumentException" val methodName2 = "testCallFactorial_NNotEqualsZero" - val methodName3 = "testCallFactorial_NLessThanZero" + val methodName3 = "testCallFactorial_NEqualsZero" val displayName1 = "n == 0 : True -> return 1" val displayName2 = "n == 0 : False -> return n * factorial(n - 1)" @@ -384,8 +384,8 @@ class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( " \n" + "Test then returns from: return invokeExample.simpleFormula(f, s);\n" - val methodName1 = "testCallSimpleInvoke_SndLessThan100" - val methodName2 = "testCallSimpleInvoke_FstLessThan100" + val methodName1 = "testCallSimpleInvoke_ThrowIllegalArgumentException" + val methodName2 = "testCallSimpleInvoke_ThrowIllegalArgumentException_1" val methodName3 = "testCallSimpleInvoke_SndGreaterOrEqual100" val displayName1 = "return invokeExample.simpleFormula(f, s) : True -> ThrowIllegalArgumentException" @@ -455,8 +455,8 @@ class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( " \n" + "Test afterwards returns from: return stringExamples.indexOf(s, key);\n" - val methodName1 = "testCallStringExample_StringIndexOf" - val methodName2 = "testCallStringExample_StringIndexOf_1" + val methodName1 = "testCallStringExample_ThrowNullPointerException" + val methodName2 = "testCallStringExample_ThrowNullPointerException_1" val methodName3 = "testCallStringExample_IEqualsZero" val methodName4 = "testCallStringExample_INotEqualsZero" val methodName5 = "testCallStringExample_IGreaterThanZero" @@ -501,16 +501,16 @@ class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( @Test fun testCallSimpleSwitch() { val summary1 = "Test calls {@link org.utbot.examples.controlflow.Switch#simpleSwitch(int)},\n" + - " there it activates switch case: 12, returns from: return 12;\n" + + " there it activates switch(x) case: 12, returns from: return 12;\n" + " " val summary2 = "Test calls {@link org.utbot.examples.controlflow.Switch#simpleSwitch(int)},\n" + - " there it activates switch case: 13, returns from: return 13;\n" + + " there it activates switch(x) case: 13, returns from: return 13;\n" + " " val summary3 = "Test calls {@link org.utbot.examples.controlflow.Switch#simpleSwitch(int)},\n" + - " there it activates switch case: 10, returns from: return 10;\n" + + " there it activates switch(x) case: 10, returns from: return 10;\n" + " " val summary4 = "Test calls {@link org.utbot.examples.controlflow.Switch#simpleSwitch(int)},\n" + - " there it activates switch case: default, returns from: return -1;\n" + + " there it activates switch(x) case: default, returns from: return -1;\n" + " " val methodName1 = "testCallSimpleSwitch_Return12" @@ -521,7 +521,7 @@ class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( val displayName1 = "switch(x) case: 12 -> return 12" val displayName2 = "switch(x) case: 13 -> return 13" val displayName3 = "switch(x) case: 10 -> return 10" - val displayName4 = "switch(x) case: Default -> return -1" + val displayName4 = "switch(x) case: default -> return -1" val method = InnerCalls::callSimpleSwitch val mockStrategy = MockStrategyApi.NO_MOCKS @@ -554,16 +554,16 @@ class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( @Test fun testCallLookup() { val summary1 = "Test calls {@link org.utbot.examples.controlflow.Switch#lookupSwitch(int)},\n" + - " there it activates switch case: 20, returns from: return 20;\n" + + " there it activates switch(x) case: 20, returns from: return 20;\n" + " " val summary2 = "Test calls {@link org.utbot.examples.controlflow.Switch#lookupSwitch(int)},\n" + - " there it activates switch case: 30, returns from: return 30;\n" + + " there it activates switch(x) case: 30, returns from: return 30;\n" + " " val summary3 = "Test calls {@link org.utbot.examples.controlflow.Switch#lookupSwitch(int)},\n" + - " there it activates switch case: 0, returns from: return 0;\n" + + " there it activates switch(x) case: 0, returns from: return 0;\n" + " " val summary4 = "Test calls {@link org.utbot.examples.controlflow.Switch#lookupSwitch(int)},\n" + - " there it activates switch case: default, returns from: return -1;\n" + + " there it activates switch(x) case: default, returns from: return -1;\n" + " " val methodName1 = "testCallLookup_Return20" @@ -574,7 +574,7 @@ class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( val displayName1 = "switch(x) case: 20 -> return 20" val displayName2 = "switch(x) case: 30 -> return 30" val displayName3 = "switch(x) case: 0 -> return 0" - val displayName4 = "switch(x) case: Default -> return -1" + val displayName4 = "switch(x) case: default -> return -1" val method = InnerCalls::callLookup val mockStrategy = MockStrategyApi.NO_MOCKS @@ -632,8 +632,8 @@ class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( " Test later returns from: return invokeExample.simpleFormula(f, s);\n" + " " - val methodName1 = "testDoubleSimpleInvoke_FstLessThan100" - val methodName2 = "testDoubleSimpleInvoke_SndLessThan100" + val methodName1 = "testDoubleSimpleInvoke_ThrowIllegalArgumentException" + val methodName2 = "testDoubleSimpleInvoke_ThrowIllegalArgumentException_1" val methodName3 = "testDoubleSimpleInvoke_SndGreaterOrEqual100" val displayName1 = "callSimpleInvoke(f, s) : True -> ThrowIllegalArgumentException" @@ -789,9 +789,9 @@ class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest( "Test throws IllegalArgumentException in: return r.fib(n);\n" val methodName1 = "testCallFib_NEquals1" - val methodName2 = "testCallFib_NEqualsZero" + val methodName2 = "testCallFib_ThrowIllegalArgumentException" val methodName3 = "testCallFib_NNotEquals1" - val methodName4 = "testCallFib_NLessThanZero" + val methodName4 = "testCallFib_NEqualsZero" val displayName1 = "n == 1 : True -> return 1" val displayName2 = "n == 0 : True -> return 0" diff --git a/utbot-summary-tests/src/test/kotlin/examples/objects/SummarySimpleClassExampleTest.kt b/utbot-summary-tests/src/test/kotlin/examples/objects/SummarySimpleClassExampleTest.kt index d2b5503eaf..0a2e69bb95 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/objects/SummarySimpleClassExampleTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/objects/SummarySimpleClassExampleTest.kt @@ -12,7 +12,7 @@ class SummarySimpleClassExampleTest : SummaryTestCaseGeneratorTest( @Test fun testImmutableFieldAccess() { val summary1 = "Test \n" + - "throws NullPointerException in: c.b == 10\n" + "throws NullPointerException when: c.b == 10\n" val summary2 = "Test executes conditions:\n" + " (c.b == 10): False\n" + "returns from: return 1;\n" diff --git a/utbot-summary-tests/src/test/kotlin/examples/recursion/SummaryRecursionTest.kt b/utbot-summary-tests/src/test/kotlin/examples/recursion/SummaryRecursionTest.kt index 8cc4f3f3d3..7fa6019ff4 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/recursion/SummaryRecursionTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/recursion/SummaryRecursionTest.kt @@ -35,12 +35,12 @@ class SummaryRecursionTest : SummaryTestCaseGeneratorTest( val summary4 = "@utbot.classUnderTest {@link Recursion}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.recursion.Recursion#fib(int)}\n" + "@utbot.executesCondition {@code (n < 0): True}\n" + - "@utbot.throwsException {@link java.lang.IllegalArgumentException} in: n < 0" + "@utbot.throwsException {@link java.lang.IllegalArgumentException} when: n < 0" val methodName1 = "testFib_Return1" val methodName2 = "testFib_ReturnZero" val methodName3 = "testFib_NNotEquals1" - val methodName4 = "testFib_NLessThanZero" + val methodName4 = "testFib_ThrowIllegalArgumentException" val displayName1 = "n == 0 : False -> return 1" val displayName2 = "n == 0 : True -> return 0" @@ -92,11 +92,11 @@ class SummaryRecursionTest : SummaryTestCaseGeneratorTest( val summary3 = "@utbot.classUnderTest {@link Recursion}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.recursion.Recursion#factorial(int)}\n" + "@utbot.executesCondition {@code (n < 0): True}\n" + - "@utbot.throwsException {@link java.lang.IllegalArgumentException} after condition: n < 0" + "@utbot.throwsException {@link java.lang.IllegalArgumentException} when: n < 0" val methodName1 = "testFactorial_Return1" val methodName2 = "testFactorial_NNotEqualsZero" - val methodName3 = "testFactorial_NLessThanZero" + val methodName3 = "testFactorial_ThrowIllegalArgumentException" //TODO: Display names are not complete, see [issue-899](https://github.com/UnitTestBot/UTBotJava/issues/899). //they should be equal "n == 0 : True -> return 1" and "n == 0 : False -> return n * factorial(n - 1)" respectively diff --git a/utbot-summary-tests/src/test/kotlin/examples/structures/SummaryMinStackTest.kt b/utbot-summary-tests/src/test/kotlin/examples/structures/SummaryMinStackTest.kt index e5061bc8e8..c920c1bf5f 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/structures/SummaryMinStackTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/structures/SummaryMinStackTest.kt @@ -63,13 +63,13 @@ class SummaryMinStackTest : SummaryTestCaseGeneratorTest( val summary1 = "@utbot.classUnderTest {@link MinStack}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.structures.MinStack#removeValue()}\n" + "@utbot.executesCondition {@code (size <= 0): True}\n" + - "@utbot.throwsException {@link java.lang.RuntimeException} after condition: size <= 0" + "@utbot.throwsException {@link java.lang.RuntimeException} when: size <= 0" val summary2 = "@utbot.classUnderTest {@link MinStack}\n" + "@utbot.methodUnderTest {@link org.utbot.examples.structures.MinStack#removeValue()}\n" + "@utbot.executesCondition {@code (size <= 0): False}\n" - val methodName1 = "testRemoveValue_SizeLessOrEqualZero" + val methodName1 = "testRemoveValue_ThrowRuntimeException" val methodName2 = "testRemoveValue_SizeGreaterThanZero" val displayName1 = "size <= 0 -> ThrowRuntimeException" @@ -145,7 +145,7 @@ class SummaryMinStackTest : SummaryTestCaseGeneratorTest( val methodName4 = "testAddValue_ThrowNullPointerException_1" val methodName5 = "testAddValue_ThrowNullPointerException_2" val methodName6 = "testAddValue_ThrowArrayIndexOutOfBoundsException_2" - val methodName7 = "testAddValue_MathMin" + val methodName7 = "testAddValue_ThrowArrayIndexOutOfBoundsException_3" val methodName8 = "testAddValue_SizeEqualsZero" val methodName9 = "testAddValue_SizeNotEqualsZero" diff --git a/utbot-summary-tests/src/test/kotlin/examples/ternary/SummaryTernaryTest.kt b/utbot-summary-tests/src/test/kotlin/examples/ternary/SummaryTernaryTest.kt index 03e11cdf83..c6c5b6dadb 100644 --- a/utbot-summary-tests/src/test/kotlin/examples/ternary/SummaryTernaryTest.kt +++ b/utbot-summary-tests/src/test/kotlin/examples/ternary/SummaryTernaryTest.kt @@ -144,7 +144,7 @@ class SummaryTernaryTest : SummaryTestCaseGeneratorTest( val methodName1 = "testParse_InputEqualsNullOrInputEquals" val methodName2 = "testParse_InputNotEqualsNullOrInputEquals" - val methodName3 = "testParse_InputEqualsNullOrInputEquals_1" + val methodName3 = "testParse_ThrowNumberFormatException" val displayName1 = "input == null || input.equals(\"\") : False -> return value" val displayName2 = "input == null || input.equals(\"\") : True -> return value" diff --git a/utbot-summary-tests/src/test/kotlin/math/SummaryIntMathLogTest.kt b/utbot-summary-tests/src/test/kotlin/math/SummaryIntMathLogTest.kt index e10db6425b..bc3b2832c4 100644 --- a/utbot-summary-tests/src/test/kotlin/math/SummaryIntMathLogTest.kt +++ b/utbot-summary-tests/src/test/kotlin/math/SummaryIntMathLogTest.kt @@ -24,17 +24,17 @@ class SummaryIntMathLogTest : SummaryTestCaseGeneratorTest( val summary4 = "@utbot.classUnderTest {@link IntMath}\n" + "@utbot.methodUnderTest {@link guava.examples.math.IntMath#log2(int,java.math.RoundingMode)}\n" + "@utbot.invokes {@link java.math.RoundingMode#ordinal()}\n" + - "@utbot.throwsException {@link java.lang.NullPointerException} in: mode" + "@utbot.throwsException {@link java.lang.NullPointerException} in: switch(mode)" val methodName1 = "testLog2_IntegerNumberOfLeadingZeros" val methodName2 = "testLog2_IntegerNumberOfLeadingZeros_1" val methodName3 = "testLog2_IntMathLessThanBranchFree" - val methodName4 = "testLog2_RoundingModeOrdinal" + val methodName4 = "testLog2_ThrowNullPointerException" val displayName1 = "switch(mode) case: FLOOR -> return (Integer.SIZE - 1) - Integer.numberOfLeadingZeros(x)" val displayName2 = "switch(mode) case: CEILING -> return Integer.SIZE - Integer.numberOfLeadingZeros(x - 1)" val displayName3 = "switch(mode) case: HALF_EVEN -> return logFloor + lessThanBranchFree(cmp, x)" - val displayName4 = "switch(mode) case: -> ThrowNullPointerException" + val displayName4 = "switch(mode) -> ThrowNullPointerException" val summaryKeys = listOf( summary1, diff --git a/utbot-summary-tests/src/test/kotlin/math/SummaryIntMathPowTest.kt b/utbot-summary-tests/src/test/kotlin/math/SummaryIntMathPowTest.kt index ec42727dd6..788874ecaa 100644 --- a/utbot-summary-tests/src/test/kotlin/math/SummaryIntMathPowTest.kt +++ b/utbot-summary-tests/src/test/kotlin/math/SummaryIntMathPowTest.kt @@ -11,7 +11,7 @@ class SummaryIntMathPowTest : SummaryTestCaseGeneratorTest( ) { @Test fun testPow() { - val summary1 = "Test activates switch case: 1, returns from: return 1;\n" + val summary1 = "Test activates switch(b) case: 1, returns from: return 1;\n" val summary2 = "Test executes conditions:\n" + " (k < Integer.SIZE): False\n" + "returns from: return 0;\n" diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/AbstractTextBuilder.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/AbstractTextBuilder.kt index b6b9ecbfd7..02c389b6f1 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/AbstractTextBuilder.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/AbstractTextBuilder.kt @@ -5,8 +5,8 @@ import com.github.javaparser.ast.expr.VariableDeclarationExpr import com.github.javaparser.ast.stmt.ExpressionStmt import com.github.javaparser.ast.stmt.ForEachStmt import com.github.javaparser.ast.stmt.ForStmt +import com.github.javaparser.ast.stmt.IfStmt import com.github.javaparser.ast.stmt.Statement -import com.github.javaparser.ast.stmt.SwitchEntry import com.github.javaparser.ast.stmt.SwitchStmt import com.github.javaparser.ast.stmt.WhileStmt import org.utbot.framework.plugin.api.Step @@ -23,8 +23,7 @@ import org.utbot.summary.tag.TraceTagWithoutExecution import soot.SootMethod import soot.jimple.Stmt import soot.jimple.internal.JIfStmt -import soot.jimple.internal.JLookupSwitchStmt -import soot.jimple.internal.JTableSwitchStmt +import soot.jimple.internal.JReturnStmt abstract class AbstractTextBuilder( val traceTag: TraceTagWithoutExecution, @@ -57,7 +56,6 @@ abstract class AbstractTextBuilder( } } - protected fun textReturn( statementTag: StatementTag, sentenceBlock: SimpleSentenceBlock, @@ -77,48 +75,22 @@ abstract class AbstractTextBuilder( returnType = StmtType.Return } jimpleToASTMap[statementTag.step.stmt]?.let { + val description = if (it is IfStmt) it.thenStmt else it sentenceBlock.stmtTexts.add( StmtDescription( returnType, - it.toString(), + description.toString(), prefix = prefixReturnText ) ) } } - - protected fun textSwitchCase(step: Step, jimpleToASTMap: JimpleToASTMap): String? { - val stmt = step.stmt - val astNode = jimpleToASTMap[stmt] - if (stmt is JLookupSwitchStmt) { - val lookup = stmt.lookupValues - val decision = step.decision - val case = ( - if (decision >= lookup.size) { - null - } else { - lookup[step.decision] - } - )?.value - - if (astNode is SwitchStmt) { - return JimpleToASTMap.getSwitchCaseLabel(astNode, case) - } - } - if (stmt is JTableSwitchStmt && astNode is SwitchStmt) { - val switchCase = JimpleToASTMap.mapSwitchCase(astNode, step) - if (switchCase is SwitchEntry) { - val case = switchCase.labels.first - return if (case.isPresent) { - "${case.get()}" - } else { - "default" - } + protected fun textSwitchCase(step: Step, jimpleToASTMap: JimpleToASTMap): String? = + (jimpleToASTMap[step.stmt] as? SwitchStmt) + ?.let { switchStmt -> + NodeConverter.convertSwitchStmt(switchStmt, step, removeSpaces = false) } - } - return null - } protected fun textCondition(statementTag: StatementTag, jimpleToASTMap: JimpleToASTMap): String? { var reversed = true diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/name/NodeConvertor.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/NodeConverter.kt similarity index 87% rename from utbot-summary/src/main/kotlin/org/utbot/summary/name/NodeConvertor.kt rename to utbot-summary/src/main/kotlin/org/utbot/summary/NodeConverter.kt index 303f130189..a1e02cfaa6 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/name/NodeConvertor.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/NodeConverter.kt @@ -1,4 +1,4 @@ -package org.utbot.summary.name +package org.utbot.summary import com.github.javaparser.ast.Node import com.github.javaparser.ast.body.VariableDeclarator @@ -41,12 +41,13 @@ import soot.jimple.internal.JIfStmt import soot.jimple.internal.JLookupSwitchStmt import soot.jimple.internal.JReturnStmt import soot.jimple.internal.JTableSwitchStmt +import kotlin.jvm.optionals.getOrNull private const val STATEMENT_DECISION_TRUE = 1 private const val STATEMENT_DECISION_FALSE = 0 -class NodeConvertor { +class NodeConverter { companion object { /** @@ -145,8 +146,9 @@ class NodeConvertor { is WhileStmt -> convertNodeToStringRecursively(ASTNode.condition, step) is IfStmt -> convertNodeToStringRecursively(ASTNode.condition, step) + is SwitchEntry -> convertSwitchEntry(ASTNode, step, removeSpaces = true) is ThrowStmt -> "Throws${ASTNode.expression.toString().removePrefix("new").capitalize()}" - is SwitchStmt -> convertSwitch(ASTNode, step) + is SwitchStmt -> convertSwitchStmt(ASTNode, step, removeSpaces = true) is ExpressionStmt -> convertNodeToStringRecursively(ASTNode.expression, step) else -> { @@ -165,7 +167,7 @@ class NodeConvertor { if (node is ExpressionStmt) node = node.expression if (node is EnclosedExpr) node = JimpleToASTMap.unEncloseExpr(node) var res = convertNodeToDisplayNameStringRecursively(node, step) - if (node is ReturnStmt) node = node.expression.orElse(null) ?: node + if (node is ReturnStmt) node = node.expression.getOrNull() ?: node if (step.stmt is JReturnStmt) return res if (nodeContainsBooleanCondition(node)) { res += if (step.decision == STATEMENT_DECISION_TRUE) { @@ -193,7 +195,7 @@ class NodeConvertor { || node is VariableDeclarationExpr && node.variables.any { nodeContainsBooleanCondition(it) } ) return true if (node is VariableDeclarator) { - val initializer = node.initializer.orElse(null) + val initializer = node.initializer.getOrNull() if (initializer != null) { return nodeContainsBooleanCondition(initializer) } @@ -214,8 +216,9 @@ class NodeConvertor { is ForStmt -> getTextIterationDescription(ASTNode) is ForEachStmt -> getTextIterationDescription(ASTNode) is IfStmt -> convertNodeToDisplayNameStringRecursively(ASTNode.condition, step) + is SwitchEntry -> convertSwitchEntry(ASTNode, step, removeSpaces = false) is ThrowStmt -> "Throws ${ASTNode.expression.toString().removePrefix("new").capitalize()}" - is SwitchStmt -> convertSwitch(ASTNode, step, removeSpaces = false) + is SwitchStmt -> convertSwitchStmt(ASTNode, step, removeSpaces = false) is ExpressionStmt -> convertNodeToDisplayNameStringRecursively(ASTNode.expression, step) is VariableDeclarationExpr -> ASTNode.variables.joinToString(separator = " ") { variable -> convertNodeToDisplayNameStringRecursively( @@ -255,43 +258,53 @@ class NodeConvertor { return res } - /** - * Converts switchNode into String - */ - private fun convertSwitch(switchNode: SwitchStmt, step: Step, removeSpaces: Boolean = true): String { - val stmt = step.stmt - var res = "" - if (stmt is JLookupSwitchStmt) { - val lookup = stmt.lookupValues - val decision = step.decision - val case = ( - if (decision >= lookup.size) { - null - } else { - lookup[step.decision] - } - )?.value - res += JimpleToASTMap.getSwitchCaseLabel(switchNode, case).capitalize() - } - if (stmt is JTableSwitchStmt) { - val switchCase = JimpleToASTMap.mapSwitchCase(switchNode, step) - if (switchCase is SwitchEntry) { - val case = switchCase.labels.first - res += if (case.isPresent) { - case.get().toString().capitalize() - } else { - "Default" - } + fun convertSwitchStmt(switchStmt: SwitchStmt, step: Step, removeSpaces: Boolean = true): String = + convertSwitchLabel(switchStmt, step) + ?.let { label -> + val selector = switchStmt.selector.toString() + formatSwitchLabel(label, selector, removeSpaces) } - } - res = if (removeSpaces) { - "Switch${switchNode.selector.toString().capitalize()}Case" + res.replace(" ", "") - } else { - "switch(${switchNode.selector}) case: " + res - } - return res + ?: "switch(${switchStmt.selector})" + + fun convertSwitchEntry(switchEntry: SwitchEntry, step: Step, removeSpaces: Boolean = true): String = + (switchEntry.parentNode.getOrNull() as? SwitchStmt) + ?.let { switchStmt -> + val label = convertSwitchLabel(switchStmt, step) ?: getSwitchLabel(switchEntry) + val selector = switchStmt.selector.toString() + formatSwitchLabel(label, selector, removeSpaces) + } + ?: switchEntry.toString() + + private fun getSwitchLabel(node: SwitchEntry): String { + val case = node.labels.first + return if (case.isPresent) "${case.get()}" else "default" + } + + private fun formatSwitchLabel(label: String, selector: String, removeSpaces: Boolean = true): String { + return if (removeSpaces) "Switch${selector.capitalize()}Case" + label.replace(" ", "") + else "switch($selector) case: $label" } + private fun convertSwitchLabel(switchStmt: SwitchStmt, step: Step): String? = + when (val stmt = step.stmt) { + is JLookupSwitchStmt -> { + val lookup = stmt.lookupValues + val case = + if (step.decision >= lookup.size) null + else lookup[step.decision].value + + JimpleToASTMap.getSwitchCaseLabel(switchStmt, case) + } + + is JTableSwitchStmt -> { + JimpleToASTMap + .mapSwitchCase(switchStmt, step) + ?.let { getSwitchLabel(it) } + } + + else -> null + } + /** * Converts literal into String */ diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/SentenceUtil.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/SentenceUtil.kt index 7558115c33..03061d0f80 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/SentenceUtil.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/SentenceUtil.kt @@ -1,6 +1,7 @@ package org.utbot.summary.comment import com.github.javaparser.ast.Node +import com.github.javaparser.ast.body.MethodDeclaration import com.github.javaparser.ast.stmt.BlockStmt import com.github.javaparser.ast.stmt.ForEachStmt import com.github.javaparser.ast.stmt.ForStmt @@ -16,6 +17,7 @@ import org.utbot.summary.SummarySentenceConstants.NEW_LINE import org.utbot.summary.SummarySentenceConstants.TAB import org.utbot.summary.comment.classic.symbolic.SquashedStmtTexts import org.utbot.summary.comment.classic.symbolic.StmtType +import kotlin.jvm.optionals.getOrNull fun numberWithSuffix(number: Int) = when (number % 10) { 1 -> "${number}st" @@ -25,21 +27,41 @@ fun numberWithSuffix(number: Int) = when (number % 10) { } /** - * Returns reason for given ThrowStmt - * It can be parent ast node - * or grandparent node if parent is BlockStmt class, + * Returns a reason for the given ThrowStmt: a condition or ThrowStmt itself. + * + * ThrowStmt is returned when its grandparent is MethodDeclaration (method under test). + * E.g. + * `public void myMethod() throws RuntimeException { throw new RuntimeException("message") }` + * + * Keep in mind, for inner method that throws something the reason will be that inner method. */ -fun getExceptionReason(throwStmt: ThrowStmt): Node? { - val parent = throwStmt.parentNode.orElse(null) - if (parent != null) { - return if (parent is BlockStmt) { - parent.parentNode.orElse(null) - } else { - parent +private fun getExceptionReason(throwStmt: ThrowStmt): Node? = + throwStmt + .parentNode + .getOrNull() + ?.let { parent -> + if (parent is BlockStmt) { + val grandParent = parent.parentNode.getOrNull() + if (grandParent is MethodDeclaration) throwStmt + else grandParent + } else parent + } + +fun getExceptionReasonForComment(throwStmt: ThrowStmt): Node? = + getExceptionReason(throwStmt) + +fun getExceptionReasonForName(throwStmt: ThrowStmt): Node? = + getExceptionReason(throwStmt) + ?.let { + if (it is ThrowStmt) { + /** + * When the node is ThrowStmt it means that we have a deal with a case + * when the method under test just throws an exception with no conditions. + * So instead of rendering the whole method in display name we want to omit it at all. + */ + null + } else it } - } - return null -} fun numberOccurrencesToText(n: Int): String = when (n) { 0 -> "" diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/classic/symbolic/SimpleCommentBuilder.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/classic/symbolic/SimpleCommentBuilder.kt index d1b88e8bee..cab592b7bb 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/classic/symbolic/SimpleCommentBuilder.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/classic/symbolic/SimpleCommentBuilder.kt @@ -1,12 +1,12 @@ package org.utbot.summary.comment.classic.symbolic -import com.github.javaparser.ast.body.MethodDeclaration import com.github.javaparser.ast.stmt.CatchClause import com.github.javaparser.ast.stmt.ForStmt import com.github.javaparser.ast.stmt.IfStmt import com.github.javaparser.ast.stmt.Statement import com.github.javaparser.ast.stmt.SwitchStmt import com.github.javaparser.ast.stmt.ThrowStmt +import com.github.javaparser.ast.stmt.SwitchEntry import org.utbot.framework.plugin.api.ArtificialError import org.utbot.framework.plugin.api.InstrumentedProcessDeathException import org.utbot.framework.plugin.api.DocPreTagStatement @@ -16,6 +16,7 @@ import org.utbot.framework.plugin.api.Step import org.utbot.framework.plugin.api.TimeoutException import org.utbot.framework.plugin.api.exceptionOrNull import org.utbot.summary.AbstractTextBuilder +import org.utbot.summary.NodeConverter import org.utbot.summary.SummarySentenceConstants.CARRIAGE_RETURN import org.utbot.summary.ast.JimpleToASTMap import org.utbot.summary.comment.* @@ -140,35 +141,41 @@ open class SimpleCommentBuilder( } /** - * Tries to find ast node where exception was thrown - * or condition if exception was thrown manually in function body + * Tries to find AST node where the exception was thrown + * or AST node that contains a condition which lead to the throw. */ - protected fun findExceptionReason(step: Step, currentMethod: SootMethod): String { - var reason = "" - val exceptionStmt = step.stmt - val jimpleToASTMap = sootToAST[currentMethod] ?: return "" - var exceptionNode = jimpleToASTMap.stmtToASTNode[exceptionStmt] - if (exceptionNode is ThrowStmt) { - exceptionNode = getExceptionReason(exceptionNode) - reason += "after condition: " - } else reason += "in: " - - //special case if reason is MethodDeclaration -> exception was thrown after body execution, not after condition - if (exceptionNode is MethodDeclaration) return "in ${exceptionNode.name} function body" - //node is SwitchStmt only when jimple stmt is inside selector - if (exceptionNode is SwitchStmt) exceptionNode = exceptionNode.selector - - if (exceptionNode == null) return "" - - reason += when { - exceptionNode is IfStmt -> exceptionNode.condition.toString() - isLoopStatement(exceptionNode) -> getTextIterationDescription(exceptionNode) - exceptionNode is SwitchStmt -> textSwitchCase(step, jimpleToASTMap) - else -> exceptionNode.toString() - } - - return reason.replace(CARRIAGE_RETURN, "") - } + private fun findExceptionReason(step: Step, currentMethod: SootMethod): String = + StringBuilder() + .let { stringBuilder -> + val jimpleToASTMap = sootToAST[currentMethod] ?: return "" + + val exceptionNode = + jimpleToASTMap.stmtToASTNode[step.stmt] + .let { node -> + if (node is ThrowStmt) getExceptionReasonForComment(node) + else node + } + ?.also { node -> + stringBuilder.append( + if (node is IfStmt || node is SwitchEntry) "when: " + else "in: " + ) + } + ?: return "" + + stringBuilder + .append( + when { + exceptionNode is IfStmt -> exceptionNode.condition.toString() + exceptionNode is SwitchEntry -> NodeConverter.convertSwitchEntry(exceptionNode, step, removeSpaces = false) + exceptionNode is SwitchStmt -> NodeConverter.convertSwitchStmt(exceptionNode, step, removeSpaces = false) + isLoopStatement(exceptionNode) -> getTextIterationDescription(exceptionNode) + else -> exceptionNode.toString() + } + ) + } + .toString() + .replace(CARRIAGE_RETURN, "") /** * Sentence blocks are built based on unique and partly unique statement tags. @@ -247,10 +254,10 @@ open class SimpleCommentBuilder( } if (statementTag.basicTypeTag == BasicTypeTag.SwitchCase && statementTag.uniquenessTag == UniquenessTag.Unique) { - val switchCase = textSwitchCase(statementTag.step, jimpleToASTMap) - if (switchCase != null) { - sentenceBlock.stmtTexts.add(StmtDescription(StmtType.SwitchCase, switchCase)) - } + textSwitchCase(statementTag.step, jimpleToASTMap) + ?.let { description -> + sentenceBlock.stmtTexts.add(StmtDescription(StmtType.SwitchCase, description)) + } } if (statementTag.basicTypeTag == BasicTypeTag.CaughtException) { jimpleToASTMap[stmt].let { diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/classic/symbolic/SimpleSentenceBlock.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/classic/symbolic/SimpleSentenceBlock.kt index f1048dee18..faa6b2fdd1 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/classic/symbolic/SimpleSentenceBlock.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/classic/symbolic/SimpleSentenceBlock.kt @@ -527,7 +527,7 @@ open class StringsTemplatesSingular : StringsTemplatesInterface { override val returnLine: String = "returns from: " override val countedReturnLine: String = "returns from:$NEW_LINE" override val invokeLine: String = "invokes:$NEW_LINE" - override val switchCaseLine: String = "activates switch case: " + override val switchCaseLine: String = "activates " override val caughtExceptionLine: String = "catches exception:$NEW_LINE" override val recursionAssignmentLine: String = "triggers recursion of " } @@ -549,7 +549,7 @@ class StringsTemplatesPlural : StringsTemplatesSingular() { override val returnLine: String = "return from: " override val countedReturnLine: String = "return from:$NEW_LINE" override val invokeLine: String = "invoke:$NEW_LINE" - override val switchCaseLine: String = "activate switch case: " + override val switchCaseLine: String = "activate " override val caughtExceptionLine: String = "catches exception:$NEW_LINE" override val recursionAssignmentLine: String = "trigger recursion of " } diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/cluster/SymbolicExecutionClusterCommentBuilder.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/cluster/SymbolicExecutionClusterCommentBuilder.kt index 6b4de29844..7ea53fbab4 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/cluster/SymbolicExecutionClusterCommentBuilder.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/cluster/SymbolicExecutionClusterCommentBuilder.kt @@ -136,10 +136,10 @@ class SymbolicExecutionClusterCommentBuilder( } if (statementTag.basicTypeTag == BasicTypeTag.SwitchCase && statementTag.uniquenessTag == UniquenessTag.Unique) { - val switchCase = textSwitchCase(statementTag.step, jimpleToASTMap) - if (switchCase != null) { - sentenceBlock.stmtTexts.add(StmtDescription(StmtType.SwitchCase, switchCase)) - } + textSwitchCase(statementTag.step, jimpleToASTMap) + ?.let { description -> + sentenceBlock.stmtTexts.add(StmtDescription(StmtType.SwitchCase, description)) + } } if (statementTag.basicTypeTag == BasicTypeTag.CaughtException && statementTag.uniquenessTag == UniquenessTag.Unique) { jimpleToASTMap[stmt].let { diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/customtags/symbolic/CustomJavaDocCommentBuilder.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/customtags/symbolic/CustomJavaDocCommentBuilder.kt index 242e93c9a6..613a9daea6 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/customtags/symbolic/CustomJavaDocCommentBuilder.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/customtags/symbolic/CustomJavaDocCommentBuilder.kt @@ -108,7 +108,7 @@ class CustomJavaDocCommentBuilder( StmtType.Condition -> comment.executesCondition += "{@code ${statement.description.replace(CARRIAGE_RETURN, "")}}" StmtType.Return -> comment.returnsFrom = "{@code ${statement.description.replace(CARRIAGE_RETURN, "")}}" StmtType.CaughtException -> comment.caughtException = "{@code ${statement.description.replace(CARRIAGE_RETURN, "")}}" - StmtType.SwitchCase -> comment.switchCase = "{@code case ${statement.description.replace(CARRIAGE_RETURN, "")}}" + StmtType.SwitchCase -> comment.switchCase = "{@code ${statement.description.replace(CARRIAGE_RETURN, "")}}" StmtType.CountedReturn -> comment.countedReturn = "{@code ${statement.description.replace(CARRIAGE_RETURN, "")}}" StmtType.RecursionAssignment -> comment.recursion = "of {@code ${statement.description.replace(CARRIAGE_RETURN, "")}}" } diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/name/NameUtil.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/name/NameUtil.kt index 48bbaec78c..483c3c8a64 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/name/NameUtil.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/name/NameUtil.kt @@ -26,6 +26,8 @@ data class TestNameDescription( if (this.uniquenessTag == UniquenessTag.Common && other.uniquenessTag == UniquenessTag.Partly) return -1 if (this.uniquenessTag == UniquenessTag.Common && other.uniquenessTag == UniquenessTag.Unique) return -1 + if (this.nameType == NameType.ThrowsException && other.nameType != NameType.ThrowsException) return 1 + if (this.nameType != NameType.ThrowsException && other.nameType == NameType.ThrowsException) return -1 if (this.nameType == NameType.CaughtException && other.nameType != NameType.CaughtException) return 1 if (this.nameType != NameType.CaughtException && other.nameType == NameType.CaughtException) return -1 @@ -47,6 +49,7 @@ data class TestNameDescription( if (this.index > other.index) return 1 if (this.index < other.index) return -1 + return 0 } } diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/name/SimpleNameBuilder.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/name/SimpleNameBuilder.kt index 478f5203de..4c51cb46a6 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/name/SimpleNameBuilder.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/name/SimpleNameBuilder.kt @@ -8,12 +8,13 @@ import org.utbot.framework.plugin.api.Step import org.utbot.framework.plugin.api.exceptionOrNull import org.utbot.framework.plugin.api.isFailure import org.utbot.summary.AbstractTextBuilder +import org.utbot.summary.NodeConverter import org.utbot.summary.SummarySentenceConstants.FROM_TO_NAMES_TRANSITION import org.utbot.summary.ast.JimpleToASTMap -import org.utbot.summary.comment.getExceptionReason +import org.utbot.summary.comment.getExceptionReasonForName import org.utbot.summary.comment.getTextTypeIterationDescription import org.utbot.summary.comment.shouldSkipInvoke -import org.utbot.summary.name.NodeConvertor.Companion.convertNodeToDisplayNameString +import org.utbot.summary.NodeConverter.Companion.convertNodeToDisplayNameString import org.utbot.summary.tag.BasicTypeTag import org.utbot.summary.tag.CallOrderTag import org.utbot.summary.tag.StatementTag @@ -91,7 +92,7 @@ class SimpleNameBuilder( private fun exceptionPlace( jimpleToASTMap: JimpleToASTMap, - placeAfter: String = " after condition: ", + placeAfter: String = " when: ", placeIn: String = " in: " ): String { if (traceTag.path.isEmpty()) return "" @@ -100,7 +101,7 @@ class SimpleNameBuilder( val lastStep = traceTag.path.last() val lastNode = jimpleToASTMap[lastStep.stmt] if (lastNode is ThrowStmt) { - val exceptionReason = getExceptionReason(lastNode) ?: return "" + val exceptionReason = getExceptionReasonForName(lastNode) ?: return "" return placeAfter + convertNodeToDisplayNameString(exceptionReason, lastStep) } else if (lastNode != null) { return placeIn + convertNodeToDisplayNameString(lastNode, lastStep) @@ -352,7 +353,7 @@ class SimpleNameBuilder( if (statementTag.uniquenessTag == UniquenessTag.Unique || (statementTag.uniquenessTag == UniquenessTag.Partly && statementTag.executionFrequency == 1) ) { - conditionName = NodeConvertor.convertNodeToString(nodeAST, statementTag.step) + conditionName = NodeConverter.convertNodeToString(nodeAST, statementTag.step) } conditionName?.let { testNames.add( @@ -372,7 +373,7 @@ class SimpleNameBuilder( var prefix = "" - var name = NodeConvertor.convertNodeToString(nodeAST, statementTag.step) + var name = NodeConverter.convertNodeToString(nodeAST, statementTag.step) var type: NameType? = null if (statementTag.basicTypeTag == BasicTypeTag.SwitchCase && statementTag.uniquenessTag == UniquenessTag.Unique) { @@ -468,7 +469,7 @@ class SimpleNameBuilder( override fun conditionStep(step: Step, reversed: Boolean, jimpleToASTMap: JimpleToASTMap): String { val nodeAST = jimpleToASTMap[step.stmt] return if (nodeAST != null) { - NodeConvertor.convertNodeToString(nodeAST, step) ?: "" + NodeConverter.convertNodeToString(nodeAST, step) ?: "" } else "" } } \ No newline at end of file