diff --git a/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummarySwitchTest.kt b/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummarySwitchTest.kt new file mode 100644 index 0000000000..13d377a1d1 --- /dev/null +++ b/utbot-summary-tests/src/test/kotlin/examples/controlflow/SummarySwitchTest.kt @@ -0,0 +1,71 @@ +package examples.controlflow + +import examples.CustomJavaDocTagsEnabler +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.framework.plugin.api.MockStrategyApi +import org.utbot.tests.infrastructure.DoNotCalculate + +@ExtendWith(CustomJavaDocTagsEnabler::class) +class SummarySwitchTest : SummaryTestCaseGeneratorTest( + Switch::class +) { + @Test + fun testDifferentExceptions() { + 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.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.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.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.returnsFrom {@code return 13;}" + + val methodName1 = "testSimpleSwitch_Return10" + val methodName2 = "testSimpleSwitch_ReturnNegative1" + val methodName3 = "testSimpleSwitch_Return12" + val methodName4 = "testSimpleSwitch_Return13" + + val displayName1 = "switch(x) case: 10 -> return 10" + val displayName2 = "switch(x) case: Default -> return -1" + val displayName3 = "switch(x) case: 12 -> return 12" + val displayName4 = "switch(x) case: 13 -> return 13" + + val summaryKeys = listOf( + summary1, + summary2, + summary3, + summary4 + ) + + val displayNames = listOf( + displayName1, + displayName2, + displayName3, + displayName4 + ) + + val methodNames = listOf( + methodName1, + methodName2, + methodName3, + methodName4 + ) + + val method = Switch::simpleSwitch + 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/exceptions/SummaryExceptionExampleTest.kt b/utbot-summary-tests/src/test/kotlin/examples/exceptions/SummaryExceptionExampleTest.kt new file mode 100644 index 0000000000..5dfca3db48 --- /dev/null +++ b/utbot-summary-tests/src/test/kotlin/examples/exceptions/SummaryExceptionExampleTest.kt @@ -0,0 +1,61 @@ +package examples.exceptions + +import examples.CustomJavaDocTagsEnabler +import examples.SummaryTestCaseGeneratorTest +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.utbot.examples.exceptions.ExceptionExamples +import org.utbot.framework.plugin.api.MockStrategyApi +import org.utbot.tests.infrastructure.DoNotCalculate + +@ExtendWith(CustomJavaDocTagsEnabler::class) +class SummaryExceptionExampleTest : SummaryTestCaseGeneratorTest( + ExceptionExamples::class +) { + @Test + fun testDifferentExceptions() { + val summary1 = "@utbot.classUnderTest {@link ExceptionExamples}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.exceptions.ExceptionExamples#nestedExceptions(int)}\n" + + "@utbot.returnsFrom {@code return checkAll(i);}" + val summary2 = "@utbot.classUnderTest {@link ExceptionExamples}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.exceptions.ExceptionExamples#nestedExceptions(int)}\n" + + "@utbot.returnsFrom {@code return -100;}\n" + + "@utbot.caughtException {@code RuntimeException e}" + val summary3 = "@utbot.classUnderTest {@link ExceptionExamples}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.exceptions.ExceptionExamples#nestedExceptions(int)}\n" + + "@utbot.returnsFrom {@code return 100;}\n" + + "@utbot.caughtException {@code NullPointerException e}" + + val methodName1 = "testNestedExceptions_ReturnCheckAll" + val methodName2 = "testNestedExceptions_CatchRuntimeException" + val methodName3 = "testNestedExceptions_CatchNullPointerException" + + val displayName1 = "-> return checkAll(i)" + val displayName2 = "Catch (RuntimeException e) -> return -100" + val displayName3 = "Catch (NullPointerException e) -> return 100" + + val summaryKeys = listOf( + summary1, + summary2, + summary3 + ) + + val displayNames = listOf( + displayName1, + displayName2, + displayName3 + ) + + val methodNames = listOf( + methodName1, + methodName2, + methodName3 + ) + + val method = ExceptionExamples::nestedExceptions + 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/recursion/SummaryRecursionTest.kt b/utbot-summary-tests/src/test/kotlin/examples/recursion/SummaryRecursionTest.kt new file mode 100644 index 0000000000..fdfee98edb --- /dev/null +++ b/utbot-summary-tests/src/test/kotlin/examples/recursion/SummaryRecursionTest.kt @@ -0,0 +1,124 @@ +package examples.recursion + +import examples.CustomJavaDocTagsEnabler +import examples.SummaryTestCaseGeneratorTest +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.utbot.examples.recursion.Recursion +import org.utbot.framework.plugin.api.MockStrategyApi +import org.utbot.tests.infrastructure.DoNotCalculate + +@ExtendWith(CustomJavaDocTagsEnabler::class) +class SummaryRecursionTest : SummaryTestCaseGeneratorTest( + Recursion::class +) { + @Test + fun testFib() { + val summary1 = "@utbot.classUnderTest {@link Recursion}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.recursion.Recursion#fib(int)}\n" + + "@utbot.executesCondition {@code (n == 0): False},\n" + + "{@code (n == 1): True}\n" + + "@utbot.returnsFrom {@code return 1;}" + val summary2 = "@utbot.classUnderTest {@link Recursion}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.recursion.Recursion#fib(int)}\n" + + "@utbot.executesCondition {@code (n == 0): True}\n" + + "@utbot.returnsFrom {@code return 0;}\n" + val summary3 = "@utbot.classUnderTest {@link Recursion}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.recursion.Recursion#fib(int)}\n" + + "@utbot.executesCondition {@code (n == 1): False}\n" + + "@utbot.returnsFrom {@code return fib(n - 1) + fib(n - 2);}" + 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" + + val methodName1 = "testFib_Return1" + val methodName2 = "testFib_ReturnZero" + val methodName3 = "testFib_NNotEquals1" + val methodName4 = "testFib_NLessThanZero" + + val displayName1 = "n == 0 : False -> return 1" + val displayName2 = "n == 0 : True -> return 0" + val displayName3 = "return 1 -> return 0" //it looks weird + val displayName4 = "n < 0 -> ThrowIllegalArgumentException" + + val summaryKeys = listOf( + summary1, + summary2, + summary3, + summary4 + ) + + val displayNames = listOf( + displayName1, + displayName2, + displayName3, + displayName4 + ) + + val methodNames = listOf( + methodName1, + methodName2, + methodName3, + methodName4 + ) + + val method = Recursion::fib + val mockStrategy = MockStrategyApi.NO_MOCKS + val coverage = DoNotCalculate + + summaryCheck(method, mockStrategy, coverage, summaryKeys, methodNames, displayNames) + } + + @Test + fun testFactorial() { + val summary1 = "@utbot.classUnderTest {@link Recursion}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.recursion.Recursion#factorial(int)}\n" + + //TODO: Lost information about executed condition, + // see [issue-900](https://github.com/UnitTestBot/UTBotJava/issues/900) + //"@utbot.executesCondition {@code (n == 0): True}\n" + "@utbot.returnsFrom {@code return 1;}" + val summary2 = "@utbot.classUnderTest {@link Recursion}\n" + + "@utbot.methodUnderTest {@link org.utbot.examples.recursion.Recursion#factorial(int)}\n" + + "@utbot.executesCondition {@code (n == 0): False}\n" + + "@utbot.returnsFrom {@code return n * factorial(n - 1);}" + 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" + + val methodName1 = "testFactorial_Return1" + val methodName2 = "testFactorial_NNotEqualsZero" + val methodName3 = "testFactorial_NLessThanZero" + + //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 + val displayName1 = "-> return 1" + val displayName2 = "-> return 1" + val displayName3 = "n < 0 -> ThrowIllegalArgumentException" + + val summaryKeys = listOf( + summary1, + summary2, + summary3 + ) + + val displayNames = listOf( + displayName1, + displayName2, + displayName3 + ) + + val methodNames = listOf( + methodName1, + methodName2, + methodName3 + ) + + val method = Recursion::factorial + 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/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocComment.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocComment.kt index 55250e8ad5..fffe9cbf8b 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocComment.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocComment.kt @@ -4,13 +4,17 @@ package org.utbot.summary.comment * Represents a set of plugin's custom JavaDoc tags. */ data class CustomJavaDocComment( - val classUnderTest: String = "", - val methodUnderTest: String = "", - val expectedResult: String = "", - val actualResult: String = "", + val classUnderTest: String = EMPTY_STRING, + val methodUnderTest: String = EMPTY_STRING, + val expectedResult: String = EMPTY_STRING, + val actualResult: String = EMPTY_STRING, var executesCondition: List = listOf(), var invokes: List = listOf(), var iterates: List = listOf(), - var returnsFrom: String = "", - var throwsException: String = "" + var switchCase: String = EMPTY_STRING, + var recursion: String = EMPTY_STRING, + var returnsFrom: String = EMPTY_STRING, + var countedReturn: String = EMPTY_STRING, + var caughtException: String = EMPTY_STRING, + var throwsException: String = EMPTY_STRING ) \ No newline at end of file diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocCommentBuilder.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocCommentBuilder.kt index 74296b5f87..8ea18fed5c 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocCommentBuilder.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocCommentBuilder.kt @@ -33,7 +33,7 @@ class CustomJavaDocCommentBuilder( ) val classReference = getClassReference(currentMethod.declaringClass.javaStyleName) - val customJavaDocComment = CustomJavaDocComment( + val comment = CustomJavaDocComment( classUnderTest = classReference, methodUnderTest = methodReference, ) @@ -49,33 +49,46 @@ class CustomJavaDocCommentBuilder( val exceptionName = thrownException.javaClass.name val reason = findExceptionReason(currentMethod, thrownException) - customJavaDocComment.throwsException = "{@link $exceptionName} $reason" + comment.throwsException = "{@link $exceptionName} $reason" } - // builds Iterates section - rootSentenceBlock.iterationSentenceBlocks.forEach { (loopDesc, sentenceBlocks) -> - customJavaDocComment.iterates += stringTemplates.iterationSentence.format( - stringTemplates.codeSentence.format(loopDesc), - numberOccurrencesToText( - sentenceBlocks.size - ) - ) - } - - // builds Invoke, Execute, Return sections generateSequence(rootSentenceBlock) { it.nextBlock }.forEach { - for (statement in it.stmtTexts) { - when (statement.stmtType) { - StmtType.Invoke -> customJavaDocComment.invokes += "{@code ${statement.description}}" - StmtType.Condition -> customJavaDocComment.executesCondition += "{@code ${statement.description}}" - StmtType.Return -> customJavaDocComment.returnsFrom = "{@code ${statement.description}}" - else -> { - //TODO: see [issue-773](https://github.com/UnitTestBot/UTBotJava/issues/773) - } + it.stmtTexts.forEach { statement -> + processStatement(statement, comment) + } + + it.invokeSentenceBlock?.let { + comment.invokes += it.first + it.second.stmtTexts.forEach { statement -> + processStatement(statement, comment) } } + + it.iterationSentenceBlocks.forEach { (loopDesc, sentenceBlocks) -> + comment.iterates += stringTemplates.iterationSentence.format( + stringTemplates.codeSentence.format(loopDesc), + numberOccurrencesToText( + sentenceBlocks.size + ) + ) + } } - return customJavaDocComment + return comment + } + + private fun processStatement( + statement: StmtDescription, + comment: CustomJavaDocComment + ) { + when (statement.stmtType) { + StmtType.Invoke -> comment.invokes += "{@code ${statement.description}}" + StmtType.Condition -> comment.executesCondition += "{@code ${statement.description}}" + StmtType.Return -> comment.returnsFrom = "{@code ${statement.description}}" + StmtType.CaughtException -> comment.caughtException = "{@code ${statement.description}}" + StmtType.SwitchCase -> comment.switchCase = "{@code case ${statement.description}}" + StmtType.CountedReturn -> comment.countedReturn = "{@code ${statement.description}}" + StmtType.RecursionAssignment -> comment.recursion = "of {@code ${statement.description}}" + } } } \ No newline at end of file diff --git a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocTagProvider.kt b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocTagProvider.kt index b1db88048b..4244605b69 100644 --- a/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocTagProvider.kt +++ b/utbot-summary/src/main/kotlin/org/utbot/summary/comment/CustomJavaDocTagProvider.kt @@ -16,7 +16,10 @@ class CustomJavaDocTagProvider { CustomJavaDocTag.Executes, CustomJavaDocTag.Invokes, CustomJavaDocTag.Iterates, + CustomJavaDocTag.SwitchCase, + CustomJavaDocTag.Recursion, CustomJavaDocTag.ReturnsFrom, + CustomJavaDocTag.CaughtException, CustomJavaDocTag.ThrowsException, ) } @@ -41,7 +44,14 @@ sealed class CustomJavaDocTag( object Invokes : CustomJavaDocTag("utbot.invokes", "Invokes", CustomJavaDocComment::invokes) object Iterates : CustomJavaDocTag("utbot.iterates", "Iterates", CustomJavaDocComment::iterates) + object SwitchCase : CustomJavaDocTag("utbot.activatesSwitch", "Activates switch", CustomJavaDocComment::switchCase) + object Recursion : + CustomJavaDocTag("utbot.triggersRecursion", "Triggers recursion ", CustomJavaDocComment::recursion) + object ReturnsFrom : CustomJavaDocTag("utbot.returnsFrom", "Returns from", CustomJavaDocComment::returnsFrom) + object CaughtException : + CustomJavaDocTag("utbot.caughtException", "Caught exception", CustomJavaDocComment::caughtException) + object ThrowsException : CustomJavaDocTag("utbot.throwsException", "Throws exception", CustomJavaDocComment::throwsException)