\n" +
- "Test executes conditions:\n" +
- " {@code (a < 0): True}\n" +
- "returns from:\n" +
- " 1st return statement: {@code return a;}\n" +
- ""
- val summaryCompare2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): True}\n" +
- "returns from:\n" +
- " 1st return statement: {@code return a;}\n" +
- ""
- val summaryCompare3 = "\n" +
- "Test executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): True}\n" +
- "returns from:\n" +
- " 1st return statement: {@code return c;}\n" +
- ""
- val summaryCompare4 = "\n" +
- "Test executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): False},\n" +
- " {@code (a > b): False},\n" +
- " {@code (a < b): True}\n" +
- "returns from:\n" +
- " 2nd return statement: {@code return a;}\n" +
- ""
- val summaryCompare5 = "\n" +
- "Test executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): False},\n" +
- " {@code (a > b): True}\n" +
- "returns from: {@code return b;}\n" +
- ""
- val summaryCompare6 = "\n" +
- "Test executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): False},\n" +
- " {@code (a > b): False},\n" +
- " {@code (a < b): False}\n" +
- "returns from:\n" +
- " 2nd return statement: {@code return c;}\n" +
- ""
-
- @Test
- fun testCompare() {
- checkTwoArguments(
- ReturnExample::compare,
- summaryKeys = listOf(
- summaryCompare1,
- summaryCompare2,
- summaryCompare3,
- summaryCompare4,
- summaryCompare5,
- summaryCompare6
- ),
- displayNames = listOf(
- "a < 0 : False -> return a",
- "b < 0 : True -> return a",
- "b == 10 : True -> return c",
- "a < b : True -> return a",
- "a > b : True -> return b",
- "a < b : False -> return c"
- )
- )
- }
-
- val summaryCompareChars1 = "\n" +
- "Test executes conditions:\n" +
- " {@code (n < 1): True}\n" +
- "returns from: {@code return ' ';}\n" +
- ""
- val summaryCompareChars2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (n < 1): False}\n" +
- "iterates the loop {@code for(int i = 0; i < n; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (Character.toChars(i)[0] == a): True}\n" +
- "returns from: {@code return b;}\n" +
- ""
- val summaryCompareChars3 = "\n" +
- "Test executes conditions:\n" +
- " {@code (n < 1): False}\n" +
- "iterates the loop {@code for(int i = 0; i < n; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (Character.toChars(i)[0] == a): False},\n" +
- " {@code (Character.toChars(i)[0] == b): True}\n" +
- "returns from:\n" +
- " 1st return statement: {@code return a;}\n" +
- ""
- val summaryCompareChars4 = "\n" +
- "Test executes conditions:\n" +
- " {@code (n < 1): False}\n" +
- "iterates the loop {@code for(int i = 0; i < n; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (Character.toChars(i)[0] == a): False},\n" +
- " {@code (Character.toChars(i)[0] == b): False}"
-
- @Test
- fun testCompareChar() {
- checkThreeArguments(
- ReturnExample::compareChars,
- summaryKeys = listOf(
- summaryCompareChars1,
- summaryCompareChars2,
- summaryCompareChars3,
- summaryCompareChars4
- ),
- displayNames = listOf(
- "n < 1 : True -> return ' '",
- "Character.toChars(i)[0] == a : True -> return b",
- "Character.toChars(i)[0] == b : True -> return a",
- "Character.toChars(i)[0] == b : False -> return a"
- )
- )
- }
-
- val summaryVoidCompareChars1 = "\n" +
- "Test calls ReturnExample::compareChars,\n" +
- " there it executes conditions:\n" +
- " {@code (n < 1): True}\n" +
- " returns from: {@code return ' ';}\n" +
- ""
- val summaryVoidCompareChars2 = "\n" +
- "Test calls ReturnExample::compareChars,\n" +
- " there it executes conditions:\n" +
- " {@code (n < 1): False}\n" +
- " iterates the loop {@code for(int i = 0; i < n; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (Character.toChars(i)[0] == a): True}\n" +
- " returns from: {@code return b;}\n" +
- ""
- val summaryVoidCompareChars3 = "\n" +
- "Test calls ReturnExample::compareChars,\n" +
- " there it executes conditions:\n" +
- " {@code (n < 1): False}\n" +
- " iterates the loop {@code for(int i = 0; i < n; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (Character.toChars(i)[0] == a): False},\n" +
- " {@code (Character.toChars(i)[0] == b): True}\n" +
- " returns from: {@code return a;}\n" +
- ""
- val summaryVoidCompareChars4 = "Test calls ReturnExample::compareChars,\n" +
- " there it executes conditions:\n" +
- " {@code (n < 1): False}\n" +
- " iterates the loop {@code for(int i = 0; i < n; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (Character.toChars(i)[0] == a): False},\n" +
- " {@code (Character.toChars(i)[0] == b): False}"
-
-
- @Test
- fun testInnerVoidCompareChars() {
- checkThreeArguments(
- ReturnExample::innerVoidCompareChars,
- summaryKeys = listOf(
- summaryVoidCompareChars1,
- summaryVoidCompareChars2,
- summaryVoidCompareChars3,
- summaryVoidCompareChars4
- ),
- displayNames = listOf(
- "n < 1 : True -> return ' '",
- "Character.toChars(i)[0] == a : True -> return b",
- "Character.toChars(i)[0] == b : True -> return a",
- "Character.toChars(i)[0] == b : False -> return a"
- )
- )
- }
-
- val summaryInnerReturnCompareChars1 = "\n" +
- "Test calls ReturnExample::compareChars,\n" +
- " there it executes conditions:\n" +
- " {@code (n < 1): True}\n" +
- " returns from: {@code return ' ';}"
- val summaryInnerReturnCompareChars2 = "Test calls ReturnExample::compareChars,\n" +
- " there it executes conditions:\n" +
- " {@code (n < 1): False}\n" +
- " iterates the loop {@code for(int i = 0; i < n; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (Character.toChars(i)[0] == a): True}\n" +
- " returns from: {@code return b;}"
- val summaryInnerReturnCompareChars3 = "Test calls ReturnExample::compareChars,\n" +
- " there it executes conditions:\n" +
- " {@code (n < 1): False}\n" +
- " iterates the loop {@code for(int i = 0; i < n; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (Character.toChars(i)[0] == a): False},\n" +
- " {@code (Character.toChars(i)[0] == b): True}\n" +
- " returns from: {@code return a;}"
- val summaryInnerReturnCompareChars4 = "Test calls ReturnExample::compareChars,\n" +
- " there it executes conditions:\n" +
- " {@code (n < 1): False}\n" +
- " iterates the loop {@code for(int i = 0; i < n; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (Character.toChars(i)[0] == a): False},\n" +
- " {@code (Character.toChars(i)[0] == b): False}"
-
- @Test
- fun testInnerReturnCompareChars() {
- checkThreeArguments(
- ReturnExample::innerReturnCompareChars,
- summaryKeys = listOf(
- summaryInnerReturnCompareChars1,
- summaryInnerReturnCompareChars2,
- summaryInnerReturnCompareChars3,
- summaryInnerReturnCompareChars4
- )
- )
- }
-
- val summaryInnerVoidCompare1 = "\n" +
- "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): True}\n" +
- " returns from: {@code return a;}\n" +
- ""
- val summaryInnerVoidCompare2 = "\n" +
- "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): True}\n" +
- " returns from: {@code return c;}\n" +
- ""
- val summaryInnerVoidCompare3 = "\n" +
- "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): False},\n" +
- " {@code (a > b): False},\n" +
- " {@code (a < b): False}\n" +
- " returns from: {@code return c;}\n" +
- ""
- val summaryInnerVoidCompare4 = "\n" +
- "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): False},\n" +
- " {@code (a > b): False},\n" +
- " {@code (a < b): True}\n" +
- " returns from: {@code return a;}\n" +
- ""
- val summaryInnerVoidCompare5 = "\n" +
- "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): True}\n" +
- " returns from: {@code return a;}\n" +
- ""
- val summaryInnerVoidCompare6 = "\n" +
- "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): False},\n" +
- " {@code (a > b): True}\n" +
- " returns from: {@code return b;}\n" +
- ""
-
- @Test
- fun testInnerVoidCompare() {
- checkTwoArguments(
- ReturnExample::innerVoidCallCompare,
- summaryKeys = listOf(
- summaryInnerVoidCompare1,
- summaryInnerVoidCompare2,
- summaryInnerVoidCompare3,
- summaryInnerVoidCompare4,
- summaryInnerVoidCompare5,
- summaryInnerVoidCompare6
- ),
- displayNames = listOf(
- "b < 0 : True -> return a",
- "b == 10 : True -> return c",
- "a < b : False -> return c",
- "a < b : True -> return a",
- "a < 0 : False -> return a",
- "a > b : True -> return b"
- )
- )
- }
-
- val summaryInnerReturnCompare1 = "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): True}\n" +
- " returns from: {@code return a;}"
- val summaryInnerReturnCompare2 = "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): True}\n" +
- " returns from: {@code return c;}"
- val summaryInnerReturnCompare3 = "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): False},\n" +
- " {@code (a > b): False},\n" +
- " {@code (a < b): False}\n" +
- " returns from: {@code return c;}"
- val summaryInnerReturnCompare4 = "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): False},\n" +
- " {@code (a > b): False},\n" +
- " {@code (a < b): True}\n" +
- " returns from: {@code return a;}"
- val summaryInnerReturnCompare5 = "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): True}\n" +
- " returns from: {@code return a;}"
- val summaryInnerReturnCompare6 = "Test calls ReturnExample::compare,\n" +
- " there it executes conditions:\n" +
- " {@code (a < 0): False},\n" +
- " {@code (b < 0): False},\n" +
- " {@code (b == 10): False},\n" +
- " {@code (a > b): True}\n" +
- " returns from: {@code return b;}"
-
- @Test
- fun testInnerReturnCompare() {
- checkTwoArguments(
- ReturnExample::innerReturnCallCompare,
- summaryKeys = listOf(
- summaryInnerReturnCompare1,
- summaryInnerReturnCompare2,
- summaryInnerReturnCompare3,
- summaryInnerReturnCompare4,
- summaryInnerReturnCompare5,
- summaryInnerReturnCompare6
- ),
- displayNames = listOf(
- "b < 0 : True -> return a",
- "b == 10 : True -> return c",
- "a < b : False -> return c",
- "a < b : True -> return a",
- "a < 0 : False -> return a",
- "a > b : True -> return b"
- )
- )
- }
-}
\ No newline at end of file
diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/controlflow/SummaryCycleTest.kt b/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/controlflow/SummaryCycleTest.kt
deleted file mode 100644
index f5e655d102..0000000000
--- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/controlflow/SummaryCycleTest.kt
+++ /dev/null
@@ -1,94 +0,0 @@
-package org.utbot.analytics.examples.controlflow
-
-import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest
-import org.utbot.examples.controlflow.Cycles
-import org.junit.jupiter.api.Test
-
-class SummaryCycleTest : SummaryTestCaseGeneratorTest(
- Cycles::class,
-) {
-
- val summaryLoopInsideLoop1 = "\n" +
- "Test iterates the loop {@code for(int i = x - 5; i < x; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i < 0): True}\n" +
- "returns from: {@code return 2;}\n" +
- ""
- val summaryLoopInsideLoop2 = "\n" +
- "Test does not iterate {@code for(int i = x - 5; i < x; i++)}, {@code for(int j = i; j < x + i; j++)}, returns from: {@code return -1;}\n" +
- ""
- val summaryLoopInsideLoop3 = "\n" +
- "Test iterates the loop {@code for(int i = x - 5; i < x; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i < 0): False}\n" +
- "iterates the loop {@code for(int j = i; j < x + i; j++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (j == 7): True}\n" +
- "returns from: {@code return 1;}\n" +
- ""
- val summaryLoopInsideLoop4 = "\n" +
- "Test iterates the loop {@code for(int i = x - 5; i < x; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i < 0): False}\n" +
- "iterates the loop {@code for(int j = i; j < x + i; j++)} twice,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (j == 7): False}\n" +
- " {@code (j == 7): True}\n" +
- "returns from: {@code return 1;}\n" +
- ""
- val summaryLoopInsideLoop5 = "\n" +
- "Test iterates the loop {@code for(int i = x - 5; i < x; i++)} 5 times."
-
- @Test
- fun testLoopInsideLoop() {
- checkOneArgument(
- Cycles::loopInsideLoop,
- summaryKeys = listOf(
- summaryLoopInsideLoop1,
- summaryLoopInsideLoop2,
- summaryLoopInsideLoop3,
- summaryLoopInsideLoop4,
- summaryLoopInsideLoop5
- ),
- displayNames = listOf(
- "i < 0 : True -> return 2",
- "-> return -1",
- "i < 0 : False -> return 1",
- "j == 7 : False -> return 1",
- "-> return -1"
- )
- )
- }
-
- val summaryStructureLoop1 = "\n" +
- "Test does not iterate {@code for(int i = 0; i < x; i++)}, returns from: {@code return -1;}\n" +
- ""
- val summaryStructureLoop2 = "\n" +
- "Test iterates the loop {@code for(int i = 0; i < x; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i == 2): False}\n"
- val summaryStructureLoop3 = "\n" +
- "Test iterates the loop {@code for(int i = 0; i < x; i++)} 3 times,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i == 2): True}\n" +
- "returns from: {@code return 1;}\n" +
- ""
-
- @Test
- fun testStructureLoop() {
- checkOneArgument(
- Cycles::structureLoop,
- summaryKeys = listOf(
- summaryStructureLoop1,
- summaryStructureLoop2,
- summaryStructureLoop3
- ),
- displayNames = listOf(
- "-> return -1",
- "i == 2 : False -> return -1",
- "i == 2 : True -> return 1"
- )
- )
- }
-
-}
\ No newline at end of file
diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryInnerCallsTest.kt b/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryInnerCallsTest.kt
deleted file mode 100644
index 976f3d969e..0000000000
--- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryInnerCallsTest.kt
+++ /dev/null
@@ -1,409 +0,0 @@
-package org.utbot.analytics.examples.inner
-
-import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest
-import org.utbot.examples.inner.InnerCalls
-import org.junit.jupiter.api.Test
-
-class SummaryInnerCallsTest : SummaryTestCaseGeneratorTest(
- InnerCalls::class,
-) {
-
- val keyCallLoopInsideLoop1 = "Test calls Cycles::loopInsideLoop,\n" +
- " there it iterates the loop {@code for(int i = x - 5; i < x; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i < 0): True}\n" +
- " returns from: {@code return 2;}"
- val keyCallLoopInsideLoop2 = "Test calls Cycles::loopInsideLoop,\n" +
- " there it iterates the loop {@code for(int i = x - 5; i < x; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i < 0): False}\n" +
- " iterates the loop {@code for(int j = i; j < x + i; j++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (j == 7): True}\n" +
- " returns from: {@code return 1;}"
- val keyCallLoopInsideLoop3 = "Test calls Cycles::loopInsideLoop,\n" +
- " there it does not iterate {@code for(int i = x - 5; i < x; i++)}, {@code for(int j = i; j < x + i; j++)}, returns from: {@code return -1;}"
- val keyCallLoopInsideLoop4 = "Test calls Cycles::loopInsideLoop,\n" +
- " there it iterates the loop {@code for(int i = x - 5; i < x; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i < 0): False}\n" +
- " iterates the loop {@code for(int j = i; j < x + i; j++)} twice,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (j == 7): False}\n" +
- " {@code (j == 7): True}\n" +
- " returns from: {@code return 1;}"
- val keyCallLoopInsideLoop5 = "Test calls Cycles::loopInsideLoop,\n" +
- " there it iterates the loop {@code for(int i = x - 5; i < x; i++)} 5 times. "
-
- @Test
- fun testCallLoopInsideLoop() {
- checkOneArgument(
- InnerCalls::callLoopInsideLoop,
- summaryKeys = listOf(
- keyCallLoopInsideLoop1,
- keyCallLoopInsideLoop2,
- keyCallLoopInsideLoop3,
- keyCallLoopInsideLoop4,
- keyCallLoopInsideLoop5
- ),
- displayNames = listOf(
- "i < 0 : True -> return 2",
- "i < 0 : False -> return 1",
- "loopInsideLoop -> return -1",
- "j == 7 : False -> return 1",
- "loopInsideLoop -> return -1"
- )
- )
- }
-
- val keyInnerCallLeftSearch1 =
- "Test throws IllegalArgumentException in: return binarySearch.leftBinSearch(array, key);"
- val keyInnerCallLeftSearch2 = "Test calls BinarySearch::leftBinSearch,\n" +
- " there it invokes:\n" +
- " BinarySearch::isUnsorted once\n" +
- " triggers recursion of leftBinSearch once.\n" +
- "Test throws NullPointerException in: return binarySearch.leftBinSearch(array, key);"
-
- val keyInnerCallLeftSearch3 = "Test calls BinarySearch::leftBinSearch,\n" +
- " there it does not iterate {@code while(left < right - 1)}, executes conditions:\n" +
- " {@code (found): False}"
- val keyInnerCallLeftSearch4 = "Test calls BinarySearch::leftBinSearch,\n" +
- " there it executes conditions:\n" +
- " {@code (isUnsorted(array)): True}\n" +
- "Test throws NullPointerException in: return binarySearch.leftBinSearch(array, key);"
-
- val keyInnerCallLeftSearch5 = "Test calls BinarySearch::leftBinSearch,\n" +
- " there it iterates the loop {@code while(left < right - 1)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (array[middle] == key): False},\n" +
- " {@code (array[middle] < key): True}"
- val keyInnerCallLeftSearch6 = "Test calls BinarySearch::leftBinSearch,\n" +
- " there it iterates the loop {@code while(left < right - 1)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (array[middle] == key): False},\n" +
- " {@code (array[middle] < key): False}"
- val keyInnerCallLeftSearch7 = "Test calls BinarySearch::leftBinSearch,\n" +
- " there it iterates the loop {@code while(left < right - 1)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (array[middle] == key): True},\n" +
- " {@code (array[middle] < key): False}"
-
-
- @Test
- fun testCallLeftBinSearch() {
- checkTwoArguments(
- InnerCalls::callLeftBinSearch,
- summaryKeys = listOf(
- keyInnerCallLeftSearch1,
- keyInnerCallLeftSearch2,
- keyInnerCallLeftSearch3,
- keyInnerCallLeftSearch4,
- keyInnerCallLeftSearch5,
- keyInnerCallLeftSearch6,
- keyInnerCallLeftSearch7
- )
- )
- }
-
- val keySummaryThreeDimensionalArray1 = "Test calls ArrayOfArrays::createNewThreeDimensionalArray,\n" +
- " there it executes conditions:\n" +
- " {@code (length != 2): True}\n" +
- " returns from: {@code return new int[0][][];}"
- val keySummaryThreeDimensionalArray2 = "Test calls ArrayOfArrays::createNewThreeDimensionalArray,\n" +
- " there it executes conditions:\n" +
- " {@code (length != 2): False}"
-
- // TODO: SAT-1211
- @Test
- fun testCallCreateNewThreeDimensionalArray() {
- checkTwoArguments(
- InnerCalls::callCreateNewThreeDimensionalArray,
- summaryKeys = listOf(
- keySummaryThreeDimensionalArray1,
- keySummaryThreeDimensionalArray2
- ),
- displayNames = listOf(
- "length != 2 : True -> return new int[0][][]",
- "length != 2 : False -> return matrix"
- )
- )
- }
-
- val summaryCallInitExample1 = "Test calls ExceptionExamples::initAnArray,\n" +
- " there it catches exception:\n" +
- " {@code NegativeArraySizeException e}\n" +
- " returns from: {@code return -2;}"
- val summaryCallInitExample2 = "Test calls ExceptionExamples::initAnArray,\n" +
- " there it catches exception:\n" +
- " {@code IndexOutOfBoundsException e}\n" +
- " returns from: {@code return -3;}"
- val summaryCallInitExample3 = "Test calls ExceptionExamples::initAnArray,\n" +
- " there it catches exception:\n" +
- " {@code IndexOutOfBoundsException e}\n" +
- " returns from: {@code return -3;}"
- val summaryCallInitExample4 = "Test calls ExceptionExamples::initAnArray,\n" +
- " there it returns from: {@code return a[n - 1] + a[n - 2];}"
-
- @Test
- fun testCallInitExamples() {
- checkOneArgument(
- InnerCalls::callInitExamples,
- summaryKeys = listOf(
- summaryCallInitExample1,
- summaryCallInitExample2,
- summaryCallInitExample3,
- summaryCallInitExample4
- )
- )
- }
-
- val summaryCallFactorial1 = "Test calls Recursion::factorial,\n" +
- " there it executes conditions:\n" +
- " {@code (n == 0): True}\n" +
- " returns from: {@code return 1;}"
- val summaryCallFactorial2 = "Test calls Recursion::factorial,\n" +
- " there it executes conditions:\n" +
- " {@code (n < 0): True}\n" +
- " triggers recursion of factorial once."
- val summaryCallFactorial3 = "Test calls Recursion::factorial,\n" +
- " there it executes conditions:\n" +
- " {@code (n == 0): False}\n" +
- " triggers recursion of factorial once, returns from: {@code return n * factorial(n - 1);}"
-
- @Test
- fun testCallFactorial() {
- checkOneArgument(
- InnerCalls::callFactorial,
- summaryKeys = listOf(
- summaryCallFactorial1,
- summaryCallFactorial2,
- summaryCallFactorial3
- ),
- displayNames = listOf(
- "n == 0 : True -> return 1",
- "n == 0 : False -> return n * factorial(n - 1)",
- "return r.factorial(n) : True -> ThrowIllegalArgumentException"
- )
- )
- }
-
- val summaryCallSimpleInvoke1 = "Test calls InvokeExample::simpleFormula,\n" +
- " there it executes conditions:\n" +
- " {@code (fst < 100): True}"
- val summaryCallSimpleInvoke2 = "Test calls InvokeExample::simpleFormula,\n" +
- " there it executes conditions:\n" +
- " {@code (fst < 100): False},\n" +
- " {@code (snd < 100): True}"
- val summaryCallSimpleInvoke3 = "Test calls InvokeExample::simpleFormula,\n" +
- " there it executes conditions:\n" +
- " {@code (fst < 100): False},\n" +
- " {@code (snd < 100): False}\n" +
- " invokes:\n" +
- " InvokeExample::half once,\n" +
- " InvokeExample::mult once"
-
- @Test
- fun testCallSimpleInvoke() {
- checkTwoArguments(
- InnerCalls::callSimpleInvoke,
- summaryKeys = listOf(
- summaryCallSimpleInvoke1,
- summaryCallSimpleInvoke2,
- summaryCallSimpleInvoke3
- )
- )
- }
-
- val summaryCallStringExample1 = "Test calls StringExamples::indexOf,\n" +
- " there it invokes:\n" +
- " String::indexOf once"
- val summaryCallStringExample2 = "Test calls StringExamples::indexOf,\n" +
- " there it invokes:\n" +
- " String::indexOf once"
- val summaryCallStringExample3 = "Test calls StringExamples::indexOf,\n" +
- " there it invokes:\n" +
- " String::indexOf once"
-
- @Test
- fun testCallComplicatedMethod() {
- checkTwoArguments(
- InnerCalls::callStringExample,
- summaryKeys = listOf(
- summaryCallStringExample1,
- summaryCallStringExample2,
- summaryCallStringExample3
- )
- )
- }
-
- val summarySimpleSwitchCase1 = "Test calls Switch::simpleSwitch,\n" +
- " there it activates switch case:"
- val summarySimpleSwitchCase2 = "Test calls Switch::simpleSwitch,\n" +
- " there it activates switch case: {@code 11}"
- val summarySimpleSwitchCase3 = "Test calls Switch::simpleSwitch,\n" +
- " there it activates switch case: {@code 12}"
- val summarySimpleSwitchCase4 = "Test calls Switch::simpleSwitch,\n" +
- " there it activates switch case: {@code 10}"
- val summarySimpleSwitchCase5 = "Test calls Switch::simpleSwitch,\n" +
- " there it activates switch case: {@code default}"
-
- @Test
- fun testCallSimpleSwitch() {
- checkOneArgument(
- InnerCalls::callSimpleSwitch,
- summaryKeys = listOf(
- summarySimpleSwitchCase1,
- summarySimpleSwitchCase2,
- summarySimpleSwitchCase3,
- summarySimpleSwitchCase4,
- summarySimpleSwitchCase5
- ),
- displayNames = listOf(
- "switch(x) case: 13 -> return 13",
- "switch(x) case: 11 -> return 12",
- "switch(x) case: 12 -> return 12",
- "switch(x) case: 10 -> return 10",
- "switch(x) case: Default -> return -1"
- )
- )
- }
-
- val summaryCallLookup1 = "Test calls Switch::lookupSwitch,\n" +
- " there it activates switch case: {@code 30}"
- val summaryCallLookup2 = "Test calls Switch::lookupSwitch,\n" +
- " there it activates switch case: {@code 10}"
- val summaryCallLookup3 = "Test calls Switch::lookupSwitch,\n" +
- " there it activates switch case: {@code 20}"
- val summaryCallLookup4 = "Test calls Switch::lookupSwitch,\n" +
- " there it activates switch case: {@code 0}"
- val summaryCallLookup5 = "Test calls Switch::lookupSwitch,\n" +
- " there it activates switch case: {@code default}"
-
- @Test
- fun testCallLookup() {
- checkOneArgument(
- InnerCalls::callLookup,
- summaryKeys = listOf(
- summaryCallLookup1,
- summaryCallLookup2,
- summaryCallLookup3,
- summaryCallLookup4,
- summaryCallLookup5
- )
- )
- }
-
- val summaryDoubleSimpleInvoke1 = "Test calls InnerCalls::callSimpleInvoke,\n" +
- " there it calls InvokeExample::simpleFormula,\n" +
- " there it executes conditions:\n" +
- " {@code (fst < 100): True}"
- val summaryDoubleSimpleInvoke2 = "Test calls InnerCalls::callSimpleInvoke,\n" +
- " there it calls InvokeExample::simpleFormula,\n" +
- " there it executes conditions:\n" +
- " {@code (fst < 100): False},\n" +
- " {@code (snd < 100): True}"
- val summaryDoubleSimpleInvoke3 = "Test calls InnerCalls::callSimpleInvoke,\n" +
- " there it calls InvokeExample::simpleFormula,\n" +
- " there it executes conditions:\n" +
- " {@code (fst < 100): False},\n" +
- " {@code (snd < 100): False}\n" +
- " invokes:\n" +
- " InvokeExample::half once,\n" +
- " InvokeExample::mult once\n" +
- " returns from: {@code return mult(x, y);}"
-
- @Test
- fun testDoubleCall() {
- checkTwoArguments(
- InnerCalls::doubleSimpleInvoke,
- summaryKeys = listOf(
- summaryDoubleSimpleInvoke1,
- summaryDoubleSimpleInvoke2,
- summaryDoubleSimpleInvoke3
- )
- )
- }
-
- val summaryDoubleCallLoopInsideLoop1 = "Test calls InnerCalls::callLoopInsideLoop,\n" +
- " there it calls Cycles::loopInsideLoop,\n" +
- " there it iterates the loop {@code for(int i = x - 5; i < x; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i < 0): True}\n" +
- " returns from: {@code return 2;}"
- val summaryDoubleCallLoopInsideLoop2 = "Test calls InnerCalls::callLoopInsideLoop,\n" +
- " there it calls Cycles::loopInsideLoop,\n" +
- " there it iterates the loop {@code for(int i = x - 5; i < x; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i < 0): False}\n" +
- " iterates the loop {@code for(int j = i; j < x + i; j++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (j == 7): True}\n" +
- " returns from: {@code return 1;}"
- val summaryDoubleCallLoopInsideLoop3 = "Test calls InnerCalls::callLoopInsideLoop,\n" +
- " there it calls Cycles::loopInsideLoop,\n" +
- " there it does not iterate {@code for(int i = x - 5; i < x; i++)}, {@code for(int j = i; j < x + i; j++)}, returns from: {@code return -1;}"
- val summaryDoubleCallLoopInsideLoop4 = "Test calls InnerCalls::callLoopInsideLoop,\n" +
- " there it calls Cycles::loopInsideLoop,\n" +
- " there it iterates the loop {@code for(int i = x - 5; i < x; i++)} once,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (i < 0): False}\n" +
- " iterates the loop {@code for(int j = i; j < x + i; j++)} 3 times,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (j == 7): False}\n" +
- " {@code (j == 7): True}\n" +
- " returns from: {@code return 1;}"
- val summaryDoubleCallLoopInsideLoop5 = "Test calls InnerCalls::callLoopInsideLoop,\n" +
- " there it calls Cycles::loopInsideLoop,\n" +
- " there it iterates the loop {@code for(int i = x - 5; i < x; i++)} 5 times."
-
-
- @Test
- fun testDoubleCallLoopInsideLoop() {
- checkOneArgument(
- InnerCalls::doubleCallLoopInsideLoop,
- summaryKeys = listOf(
- summaryDoubleCallLoopInsideLoop1,
- summaryDoubleCallLoopInsideLoop2,
- summaryDoubleCallLoopInsideLoop3,
- summaryDoubleCallLoopInsideLoop4,
- summaryDoubleCallLoopInsideLoop5,
- )
- )
- }
-
- val summaryCallFib1 = "Test calls Recursion::fib,\n" +
- " there it executes conditions:\n" +
- " {@code (n == 0): True}"
- val summaryCallFib2 = "Test calls Recursion::fib,\n" +
- " there it executes conditions:\n" +
- " {@code (n == 0): False},\n" +
- " {@code (n == 1): True}"
- val summaryCallFib3 = "Test calls Recursion::fib,\n" +
- " there it executes conditions:\n" +
- " {@code (n == 0): False},\n" +
- " {@code (n == 1): False}\n" +
- " triggers recursion of fib twice, returns from: {@code return fib(n - 1) + fib(n - 2);}"
- val summaryCallFib4 = "Test calls Recursion::fib,\n" +
- " there it executes conditions:\n" +
- " {@code (n < 0): True}\n" +
- " triggers recursion of fib once."
-
- @Test
- fun testInnerCallFib() {
- checkOneArgument(
- InnerCalls::callFib,
- summaryKeys = listOf(
- summaryCallFib1,
- summaryCallFib2,
- summaryCallFib3,
- summaryCallFib4
- ),
- displayNames = listOf(
- "n == 0 : True -> return 0",
- "n == 1 : True -> return 1",
- "n == 1 : False -> return fib(n - 1) + fib(n - 2)",
- "return r.fib(n) : True -> ThrowIllegalArgumentException"
- )
- )
- }
-}
\ No newline at end of file
diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryNestedCallsTest.kt b/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryNestedCallsTest.kt
deleted file mode 100644
index 3e831c2e9e..0000000000
--- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/inner/SummaryNestedCallsTest.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.utbot.analytics.examples.inner
-
-import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest
-import org.utbot.examples.inner.NestedCalls
-import org.junit.jupiter.api.Test
-
-class SummaryNestedCallsTest : SummaryTestCaseGeneratorTest(
- NestedCalls::class,
-) {
-
- val summaryNestedCall1 = "Test calls NestedCalls\$ExceptionExamples::initAnArray,\n" +
- " there it catches exception:\n" +
- " {@code NegativeArraySizeException e}"
- val summaryNestedCall2 = "Test calls NestedCalls\$ExceptionExamples::initAnArray,\n" +
- " there it catches exception:\n" +
- " {@code IndexOutOfBoundsException e}"
- val summaryNestedCall3 = "Test calls NestedCalls\$ExceptionExamples::initAnArray,\n" +
- " there it catches exception:\n" +
- " {@code IndexOutOfBoundsException e}"
- val summaryNestedCall4 = "\n" +
- "Test calls NestedCalls\$ExceptionExamples::initAnArray,\n" +
- " there it returns from: {@code return a[n - 1] + a[n - 2];}"
-
- @Test
- fun testInvokeExample() {
- checkOneArgument(
- NestedCalls::callInitExamples,
- summaryKeys = listOf(
- summaryNestedCall1,
- summaryNestedCall2,
- summaryNestedCall3,
- summaryNestedCall4,
- ),
- displayNames = listOf(
- "Catch (NegativeArraySizeException e) -> return -2",
- "Catch (IndexOutOfBoundsException e) -> return -3",
- "Catch (IndexOutOfBoundsException e) -> return -3",
- "initAnArray -> return a[n - 1] + a[n - 2]"
- )
- )
- }
-}
\ No newline at end of file
diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/ternary/SummaryTernary.kt b/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/ternary/SummaryTernary.kt
deleted file mode 100644
index 8d3571feb1..0000000000
--- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/examples/ternary/SummaryTernary.kt
+++ /dev/null
@@ -1,381 +0,0 @@
-package org.utbot.analytics.examples.ternary
-
-import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest
-import org.utbot.examples.ternary.Ternary
-import org.junit.jupiter.api.Tag
-import org.junit.jupiter.api.Test
-
-class SummaryTernary : SummaryTestCaseGeneratorTest(
- Ternary::class,
-) {
-
- val summaryMax1 = "\n" +
- "Test executes conditions:\n" +
- " {@code (val1 >= val2): False}\n" +
- "returns from: {@code return val1 >= val2 ? val1 : val2;}\n" +
- ""
- val summaryMax2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (val1 >= val2): True}\n" +
- "returns from: {@code return val1 >= val2 ? val1 : val2;}\n" +
- ""
-
- @Test
- fun testMax() {
- checkTwoArguments(
- Ternary::max,
- summaryKeys = listOf(
- summaryMax1,
- summaryMax2
- ),
- displayNames = listOf(
- "val1 >= val2 : False -> return val1 >= val2 ? val1 : val2",
- "val1 >= val2 : True -> return val1 >= val2 ? val1 : val2"
- )
- )
- }
-
- val summarySimpleOperation = "\n" +
- "Test returns from: {@code return result;}\n" +
- ""
-
- @Test
- fun testSimpleOperation() {
- checkTwoArguments(
- Ternary::simpleOperation,
- summaryKeys = listOf(summarySimpleOperation),
- displayNames = listOf(
- "-> return result"
- )
- )
- }
-
- val summaryStringExpr1 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num > 10): True}\n" +
- "returns from: {@code return num > 10 ? \"Number is greater than 10\" : num > 5 ? \"Number is greater than 5\" : \"Number is less than equal to 5\";}\n" +
- ""
- val summaryStringExpr2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num > 10): False},\n" +
- " {@code (num > 5): False}\n" +
- "returns from: {@code return num > 10 ? \"Number is greater than 10\" : num > 5 ? \"Number is greater than 5\" : \"Number is less than equal to 5\";}\n" +
- ""
- val summaryStringExpr3 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num > 10): False},\n" +
- " {@code (num > 5): True}\n" +
- "returns from: {@code return num > 10 ? \"Number is greater than 10\" : num > 5 ? \"Number is greater than 5\" : \"Number is less than equal to 5\";}\n" +
- ""
-
- @Test
- fun testStringExpr() {
- checkOneArgument(
- Ternary::stringExpr,
- summaryKeys = listOf(
- summaryStringExpr1,
- summaryStringExpr2,
- summaryStringExpr3
- )
- )
- }
-
- @Test
- @Tag("slow")
- fun testParse() {
- checkOneArgument(
- Ternary::parse,
- summaryKeys = listOf()
- )
- }
-
- val summaryMinValue1 = "\n" +
- "Test executes conditions:\n" +
- " {@code ((a < b)): False}\n" +
- "returns from: {@code return (a < b) ? a : b;}\n" +
- ""
- val summaryMinValue2 = "\n" +
- "Test executes conditions:\n" +
- " {@code ((a < b)): True}\n" +
- "returns from: {@code return (a < b) ? a : b;}\n" +
- ""
-
- @Test
- fun testMinValue() {
- checkTwoArguments(
- Ternary::minValue,
- summaryKeys = listOf(
- summaryMinValue1,
- summaryMinValue2
- ),
- displayNames = listOf(
- "a < b : False -> return (a < b) ? a : b",
- "a < b : True -> return (a < b) ? a : b"
- )
- )
- }
-
- val summarySubDelay1 = "\n" +
- "Test executes conditions:\n" +
- " {@code (flag): False}\n" +
- "returns from: {@code return flag ? 100 : 0;}\n" +
- ""
- val summarySubDelay2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (flag): True}\n" +
- "returns from: {@code return flag ? 100 : 0;}\n" +
- ""
-
- @Test
- fun testSubDelay() {
- checkOneArgument(
- Ternary::subDelay,
- summaryKeys = listOf(
- summarySubDelay1,
- summarySubDelay2
- ),
- displayNames = listOf(
- "flag : False -> return flag ? 100 : 0",
- "flag : True -> return flag ? 100 : 0"
- )
- )
- }
-
- val summaryPlusOrMinus1 = "\n" +
- "Test executes conditions:\n" +
- " {@code ((num1 > num2)): False}\n" +
- "returns from: {@code return (num1 > num2) ? (num1 + num2) : (num1 - num2);}\n" +
- ""
- val summaryPlusOrMinus2 = "\n" +
- "Test executes conditions:\n" +
- " {@code ((num1 > num2)): True}\n" +
- "returns from: {@code return (num1 > num2) ? (num1 + num2) : (num1 - num2);}\n" +
- ""
-
- @Test
- fun testPlusOrMinus() {
- checkTwoArguments(
- Ternary::plusOrMinus,
- summaryKeys = listOf(
- summaryPlusOrMinus1,
- summaryPlusOrMinus2
- )
- )
- }
-
- val summaryLongTernary1 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): True}\n" +
- "returns from: {@code return num1 > num2 ? 1 : num1 == num2 ? 2 : 3;}\n" +
- ""
- val summaryLongTernary2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): False},\n" +
- " {@code (num1 == num2): True}\n" +
- "returns from: {@code return num1 > num2 ? 1 : num1 == num2 ? 2 : 3;}\n" +
- ""
- val summaryLongTernary3 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): False},\n" +
- " {@code (num1 == num2): False}\n" +
- "returns from: {@code return num1 > num2 ? 1 : num1 == num2 ? 2 : 3;}\n" +
- ""
-
- @Test
- fun testLongTernary() {
- checkTwoArguments(
- Ternary::longTernary,
- summaryKeys = listOf(
- summaryLongTernary1,
- summaryLongTernary2,
- summaryLongTernary3
- )
- )
- }
-
- val summaryVeryLongTernary1 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): True}\n" +
- "returns from: {@code return num1 > num2 ? 1 : num1 == num2 ? 2 : num2 > num3 ? 3 : num2 == num3 ? 4 : 5;}\n" +
- ""
- val summaryVeryLongTernary2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): False},\n" +
- " {@code (num1 == num2): False},\n" +
- " {@code (num2 > num3): False},\n" +
- " {@code (num2 == num3): False}\n" +
- "returns from: {@code return num1 > num2 ? 1 : num1 == num2 ? 2 : num2 > num3 ? 3 : num2 == num3 ? 4 : 5;}\n" +
- ""
- val summaryVeryLongTernary3 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): False},\n" +
- " {@code (num1 == num2): True}\n" +
- "returns from: {@code return num1 > num2 ? 1 : num1 == num2 ? 2 : num2 > num3 ? 3 : num2 == num3 ? 4 : 5;}\n" +
- ""
- val summaryVeryLongTernary4 = "Test executes conditions:\n" +
- " {@code (num1 > num2): False},\n" +
- " {@code (num1 == num2): False},\n" +
- " {@code (num2 > num3): False},\n" +
- " {@code (num2 == num3): True}\n" +
- "returns from: {@code return num1 > num2 ? 1 : num1 == num2 ? 2 : num2 > num3 ? 3 : num2 == num3 ? 4 : 5;}\n" +
- ""
- val summaryVeryLongTernary5 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): False},\n" +
- " {@code (num1 == num2): False},\n" +
- " {@code (num2 > num3): True}\n" +
- "returns from: {@code return num1 > num2 ? 1 : num1 == num2 ? 2 : num2 > num3 ? 3 : num2 == num3 ? 4 : 5;}\n" +
- ""
-
- @Test
- fun testVeryLongTernary() {
- checkThreeArguments(
- Ternary::veryLongTernary,
- summaryKeys = listOf(
- summaryVeryLongTernary1,
- summaryVeryLongTernary2,
- summaryVeryLongTernary3,
- summaryVeryLongTernary4,
- summaryVeryLongTernary5
- )
- )
- }
-
- val summaryMinMax1 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): False}\n" +
- "calls Ternary::minValue,\n" +
- " there it executes conditions:\n" +
- " {@code ((a < b)): True}\n" +
- " returns from: {@code return (a < b) ? a : b;}"
- val summaryMinMax2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): True}\n" +
- "calls Ternary::max,\n" +
- " there it executes conditions:\n" +
- " {@code (val1 >= val2): True}\n" +
- " returns from: {@code return val1 >= val2 ? val1 : val2;}"
- val summaryMinMax3 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): False}\n" +
- "calls Ternary::minValue,\n" +
- " there it executes conditions:\n" +
- " {@code ((a < b)): False}\n" +
- " returns from: {@code return (a < b) ? a : b;}"
-
- @Test
- fun testMinMax() {
- checkTwoArguments(
- Ternary::minMax,
- summaryKeys = listOf(
- summaryMinMax1,
- summaryMinMax2,
- summaryMinMax3
- )
- )
- }
-
- val summaryIncFunc1 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): False}\n" +
- "invokes:\n" +
- " Ternary::intFunc2 once\n" +
- "returns from: {@code return num1 > num2 ? intFunc1() : intFunc2();}\n" +
- ""
- val summaryIncFunc2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): True}\n" +
- "invokes:\n" +
- " Ternary::intFunc1 once\n" +
- "returns from: {@code return num1 > num2 ? intFunc1() : intFunc2();}\n" +
- ""
-
- @Test
- fun testIntFunc() {
- checkTwoArguments(
- Ternary::intFunc,
- summaryKeys = listOf(
- summaryIncFunc1,
- summaryIncFunc2
- ),
- displayNames = listOf(
- "num1 > num2 : False -> return num1 > num2 ? intFunc1() : intFunc2()",
- "num1 > num2 : True -> return num1 > num2 ? intFunc1() : intFunc2()"
- )
- )
- }
-
- val summaryTernaryInTheMiddle1 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num2 > num3): True}\n" +
- "calls Ternary::max,\n" +
- " there it executes conditions:\n" +
- " {@code (val1 >= val2): False}\n" +
- " returns from: {@code return val1 >= val2 ? val1 : val2;}"
- val summaryTernaryInTheMiddle2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num2 > num3): False}\n" +
- "calls Ternary::max,\n" +
- " there it executes conditions:\n" +
- " {@code (val1 >= val2): False}\n" +
- " returns from: {@code return val1 >= val2 ? val1 : val2;}"
- val summaryTernaryInTheMiddle3 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num2 > num3): False}\n" +
- "calls Ternary::max,\n" +
- " there it executes conditions:\n" +
- " {@code (val1 >= val2): True}\n" +
- " returns from: {@code return val1 >= val2 ? val1 : val2;}"
-
- @Test
- fun testTernaryInTheMiddle() {
- checkThreeArguments(
- Ternary::ternaryInTheMiddle,
- summaryKeys = listOf(
- summaryTernaryInTheMiddle1,
- summaryTernaryInTheMiddle2,
- summaryTernaryInTheMiddle3
- ),
- displayNames = listOf(
- "val1 >= val2 : False -> return val1 >= val2 ? val1 : val2",
- "val2 : False -> return val1 >= val2 ? val1 : val2",
- "val1 >= val2 : True -> return val1 >= val2 ? val1 : val2"
- )
- )
- }
-
- val summaryTwoIfsOneLine1 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): False}\n" +
- "returns from: {@code return a;}\n" +
- ""
- val summaryTwoIfsOneLine2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): True},\n" +
- " {@code ((num1 - 10) > 0): False}\n" +
- "returns from: {@code return a;}\n" +
- ""
- val summaryTwoIfsOneLine3 = "\n" +
- "Test executes conditions:\n" +
- " {@code (num1 > num2): True},\n" +
- " {@code ((num1 - 10) > 0): True}\n" +
- "returns from: {@code return a;}\n" +
- ""
-
- @Test
- fun testTwoIfsOneLine() {
- checkTwoArguments(
- Ternary::twoIfsOneLine,
- summaryKeys = listOf(
- summaryTwoIfsOneLine1,
- summaryTwoIfsOneLine2,
- summaryTwoIfsOneLine3
- ),
- displayNames = listOf(
- "num1 > num2 : False -> return a",
- "(num1 - 10) > 0 : False -> return a",
- "(num1 - 10) > 0 : True -> return a"
- )
- )
- }
-}
\ No newline at end of file
diff --git a/utbot-analytics/src/test/kotlin/org/utbot/analytics/guava/math/SummaryIntMath.kt b/utbot-analytics/src/test/kotlin/org/utbot/analytics/guava/math/SummaryIntMath.kt
deleted file mode 100644
index d92c84f9d3..0000000000
--- a/utbot-analytics/src/test/kotlin/org/utbot/analytics/guava/math/SummaryIntMath.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.utbot.analytics.guava.math
-
-import org.utbot.analytics.examples.SummaryTestCaseGeneratorTest
-import guava.examples.math.IntMath
-import org.junit.jupiter.api.Test
-
-class SummaryIntMath : SummaryTestCaseGeneratorTest(
- IntMath::class,
-) {
-
- //TODO SAT-1205
- @Test
- fun testLog2() {
- checkOneArgument(
- IntMath::log2,
- summaryKeys = listOf()
- )
- }
-
- @Test
- fun testPow() {
- val summaryPow1 = "\n" +
- "Test activates switch case: {@code 2}, returns from: {@code return 1;}\n" +
- ""
- val summaryPow2 = "\n" +
- "Test executes conditions:\n" +
- " {@code (k < Integer.SIZE): False}\n" +
- "returns from: {@code return 0;}\n" +
- ""
- val summaryPow3 = "\n" +
- "Test executes conditions:\n" +
- " {@code ((k < Integer.SIZE)): False}\n" +
- "returns from: {@code return (k < Integer.SIZE) ? (1 << k) : 0;}\n" +
- ""
- val summaryPow4 = "\n" +
- "Test iterates the loop {@code for(int accum = 1; ; k >>= 1)} once,\n" +
- " inside this loop, the test returns from: {@code return b * accum;}\n" +
- ""
- val summaryPow5 = "\n" +
- "Test executes conditions:\n" +
- " {@code ((k < Integer.SIZE)): True}\n" +
- "returns from: {@code return (k < Integer.SIZE) ? (1 << k) : 0;}\n" +
- ""
- val summaryPow6 = "\n" +
- "Test executes conditions:\n" +
- " {@code ((k == 0)): False}\n" +
- "returns from: {@code return (k == 0) ? 1 : 0;}\n" +
- ""
- val summaryPow7 = "\n" +
- "Test iterates the loop {@code for(int accum = 1; ; k >>= 1)} once,\n" +
- " inside this loop, the test returns from: {@code return accum;}\n" +
- ""
- val summaryPow8 = "\n" +
- "Test executes conditions:\n" +
- " {@code ((k == 0)): True}\n" +
- "returns from: {@code return (k == 0) ? 1 : 0;}\n" +
- ""
- val summaryPow9 = "\n" +
- "Test executes conditions:\n" +
- " {@code (k < Integer.SIZE): True},\n" +
- " {@code (((k & 1) == 0)): True}\n" +
- "returns from: {@code return ((k & 1) == 0) ? (1 << k) : -(1 << k);}\n" +
- ""
- val summaryPow10 = "\n" +
- "Test iterates the loop {@code for(int accum = 1; ; k >>= 1)} twice,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (((k & 1) == 0)): False}\n" +
- ", returns from: {@code return b * accum;}\n" +
- ""
- val summaryPow11 = "\n" +
- "Test executes conditions:\n" +
- " {@code (((k & 1) == 0)): False}\n" +
- "returns from: {@code return ((k & 1) == 0) ? 1 : -1;}\n" +
- ""
- val summaryPow12 = "\n" +
- "Test executes conditions:\n" +
- " {@code (k < Integer.SIZE): True},\n" +
- " {@code (((k & 1) == 0)): False}\n" +
- "returns from: {@code return ((k & 1) == 0) ? (1 << k) : -(1 << k);}\n" +
- ""
- val summaryPow13 = "\n" +
- "Test executes conditions:\n" +
- " {@code (((k & 1) == 0)): True}\n" +
- "returns from: {@code return ((k & 1) == 0) ? 1 : -1;}\n" +
- ""
- val summaryPow14 = "\n" +
- "Test iterates the loop {@code for(int accum = 1; ; k >>= 1)} twice,\n" +
- " inside this loop, the test executes conditions:\n" +
- " {@code (((k & 1) == 0)): True}\n" +
- ", returns from: {@code return b * accum;}\n" +
- ""
- checkOneArgument(
- IntMath::pow,
- summaryKeys = listOf(
- summaryPow1,
- summaryPow2,
- summaryPow3,
- summaryPow4,
- summaryPow5,
- summaryPow6,
- summaryPow7,
- summaryPow8,
- summaryPow9,
- summaryPow10,
- summaryPow11,
- summaryPow12,
- summaryPow13,
- summaryPow14
- )
- )
- }
-}
\ No newline at end of file
diff --git a/utbot-analytics/src/test/kotlin/org/utbot/features/FeatureProcessorWithRepetitionTest.kt b/utbot-analytics/src/test/kotlin/org/utbot/features/FeatureProcessorWithRepetitionTest.kt
new file mode 100644
index 0000000000..3c0176fd3e
--- /dev/null
+++ b/utbot-analytics/src/test/kotlin/org/utbot/features/FeatureProcessorWithRepetitionTest.kt
@@ -0,0 +1,111 @@
+package org.utbot.features
+
+import org.junit.jupiter.api.AfterAll
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.BeforeAll
+import org.junit.jupiter.api.Test
+import org.utbot.analytics.EngineAnalyticsContext
+import org.utbot.examples.AbstractTestCaseGeneratorTest
+import org.utbot.examples.eq
+import org.utbot.examples.withFeaturePath
+import java.io.File
+import java.io.FileInputStream
+
+class FeatureProcessorWithRepetitionTest : AbstractTestCaseGeneratorTest(OnePath::class, false) {
+ companion object {
+ const val featureDir = "src/test/resources/features"
+ fun reward(coverage: Double, time: Double) = RewardEstimator.reward(coverage, time)
+
+ @JvmStatic
+ @BeforeAll
+ fun beforeAll() {
+ File(featureDir).mkdir()
+ EngineAnalyticsContext.featureProcessorFactory = FeatureProcessorWithStatesRepetitionFactory()
+ EngineAnalyticsContext.featureExtractorFactory = FeatureExtractorFactoryImpl()
+ }
+
+ @JvmStatic
+ @AfterAll
+ fun afterAll() {
+ File(featureDir).deleteRecursively()
+ }
+ }
+
+ @Test
+ fun testCalculateRewards() {
+ val statesToInt = mapOf(
+ "a0" to 1,
+ "c0" to 2,
+ "f0" to 3,
+ "g0" to 4,
+ "c1" to 5,
+ "f1" to 6,
+ "g1" to 7,
+ "b0" to 8,
+ "d0" to 9
+ )
+
+ val expectedRewards: Map = mapOf(
+ "a0" to reward(6.0, 15.0),
+ "c0" to reward(4.0, 10.0),
+ "f0" to reward(4.0, 8.0),
+ "g0" to reward(4.0, 2.0),
+ "c1" to reward(0.0, 4.0),
+ "f1" to reward(0.0, 3.0),
+ "g1" to reward(0.0, 2.0),
+ "b0" to reward(2.0, 4.0),
+ "d0" to reward(2.0, 2.0)
+ )
+
+ val rewardEstimator = RewardEstimator()
+ val testCases = listOf(
+ TestCase(
+ listOf(
+ statesToInt["g0"]!! to 2L,
+ statesToInt["f0"]!! to 2L,
+ statesToInt["c0"]!! to 2L,
+ statesToInt["a0"]!! to 1L
+ ),
+ newCoverage = 4, testIndex = 0
+ ),
+ TestCase(
+ listOf(
+ statesToInt["g1"]!! to 2L,
+ statesToInt["f1"]!! to 1L,
+ statesToInt["c1"]!! to 1L,
+ statesToInt["f0"]!! to 2L,
+ statesToInt["c0"]!! to 2L,
+ statesToInt["a0"]!! to 1L
+ ),
+ newCoverage = 0,
+ testIndex = 1
+ ),
+ TestCase(
+ listOf(statesToInt["d0"]!! to 2L, statesToInt["b0"]!! to 2L, statesToInt["a0"]!! to 1L),
+ newCoverage = 2,
+ testIndex = 2
+ )
+ )
+
+ val rewards = rewardEstimator.calculateRewards(testCases)
+ Assertions.assertEquals(9, rewards.size)
+ expectedRewards.forEach {
+ Assertions.assertEquals(it.value, rewards[statesToInt[it.key]])
+ }
+ }
+
+ /**
+ * Test, that we correctly add test cases and dump them into file
+ */
+ @Test
+ fun addTestCaseTest() {
+ withFeaturePath(featureDir) {
+ check(
+ OnePath::onePath,
+ eq(1)
+ )
+
+ Assertions.assertTrue(FileInputStream("$featureDir/0.csv").bufferedReader().readLines().size > 1)
+ }
+ }
+}
diff --git a/utbot-analytics/src/test/kotlin/org/utbot/predictors/LinearStateRewardPredictorTest.kt b/utbot-analytics/src/test/kotlin/org/utbot/predictors/LinearStateRewardPredictorTest.kt
new file mode 100644
index 0000000000..6a68e83212
--- /dev/null
+++ b/utbot-analytics/src/test/kotlin/org/utbot/predictors/LinearStateRewardPredictorTest.kt
@@ -0,0 +1,45 @@
+package org.utbot.predictors
+
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+import org.utbot.examples.withPathSelectorType
+import org.utbot.examples.withRewardModelPath
+import org.utbot.framework.PathSelectorType
+import org.utbot.framework.UtSettings
+
+class LinearStateRewardPredictorTest {
+ @Test
+ fun simpleTest() {
+ withRewardModelPath("src/test/resources") {
+ val pred = LinearStateRewardPredictor()
+
+ val features = listOf(
+ listOf(2.0, 3.0),
+ listOf(2.0, 3.0)
+ )
+
+ assertEquals(listOf(6.0, 6.0), pred.predict(features))
+ }
+ }
+
+ @Test
+ fun wrongFormatTest() {
+ withRewardModelPath("src/test/resources") {
+ withPathSelectorType(PathSelectorType.NN_REWARD_GUIDED_SELECTOR) {
+ LinearStateRewardPredictor("wrong_format_linear.txt")
+ assertEquals(PathSelectorType.INHERITORS_SELECTOR, UtSettings.pathSelectorType)
+ }
+ }
+ }
+
+ @Test
+ fun simpleTestNotBatch() {
+ withRewardModelPath("src/test/resources") {
+ val pred = LinearStateRewardPredictor()
+
+ val features = listOf(2.0, 3.0)
+
+ assertEquals(6.0, pred.predict(features))
+ }
+ }
+}
\ No newline at end of file
diff --git a/utbot-analytics/src/test/kotlin/org/utbot/predictors/NNStateRewardPredictorTest.kt b/utbot-analytics/src/test/kotlin/org/utbot/predictors/NNStateRewardPredictorTest.kt
new file mode 100644
index 0000000000..42dd3bac40
--- /dev/null
+++ b/utbot-analytics/src/test/kotlin/org/utbot/predictors/NNStateRewardPredictorTest.kt
@@ -0,0 +1,86 @@
+package org.utbot.predictors
+
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Disabled
+import org.junit.jupiter.api.Test
+import org.utbot.examples.withPathSelectorType
+import org.utbot.analytics.StateRewardPredictor
+import org.utbot.examples.withRewardModelPath
+import org.utbot.framework.PathSelectorType
+import org.utbot.framework.UtSettings
+import kotlin.system.measureNanoTime
+
+class NNStateRewardPredictorTest {
+ @Test
+ fun simpleTest() {
+ withRewardModelPath("src/test/resources") {
+ val pred = NNStateRewardPredictorBase()
+
+ val features = listOf(0.0, 0.0)
+
+ assertEquals(5.0, pred.predict(features))
+ }
+ }
+
+ @Disabled("Just to see the performance of predictors")
+ @Test
+ fun performanceTest() {
+ val features = (1..13).map { 1.0 }.toList()
+ withRewardModelPath("models\\test\\0") {
+ val averageTime = calcAverageTimeForModelPredict(::NNStateRewardPredictorBase, 100, features)
+ println(averageTime)
+ }
+
+
+ withRewardModelPath("models") {
+ val averageTime = calcAverageTimeForModelPredict(::StateRewardPredictorTorch, 100, features)
+ println(averageTime)
+ }
+ }
+
+ private fun calcAverageTimeForModelPredict(
+ model: () -> StateRewardPredictor,
+ iterations: Int,
+ features: List
+ ): Double {
+ val pred = model()
+
+ (1..iterations).map {
+ pred.predict(features)
+ }
+
+ return (1..iterations)
+ .map { measureNanoTime { pred.predict(features) } }
+ .average()
+ }
+
+ @Test
+ fun corruptedModelFileTest() {
+ withRewardModelPath("src/test/resources") {
+ withPathSelectorType(PathSelectorType.NN_REWARD_GUIDED_SELECTOR) {
+ NNStateRewardPredictorBase(modelPath = "corrupted_nn.json")
+ assertEquals(PathSelectorType.INHERITORS_SELECTOR, UtSettings.pathSelectorType)
+ }
+ }
+ }
+
+ @Test
+ fun emptyModelFileTest() {
+ withRewardModelPath("src/test/resources") {
+ withPathSelectorType(PathSelectorType.NN_REWARD_GUIDED_SELECTOR) {
+ NNStateRewardPredictorBase(modelPath = "empty_nn.json")
+ assertEquals(PathSelectorType.INHERITORS_SELECTOR, UtSettings.pathSelectorType)
+ }
+ }
+ }
+
+ @Test
+ fun corruptedScalerTest() {
+ withRewardModelPath("src/test/resources") {
+ withPathSelectorType(PathSelectorType.NN_REWARD_GUIDED_SELECTOR) {
+ NNStateRewardPredictorBase(scalerPath = "corrupted_scaler.txt")
+ assertEquals(PathSelectorType.INHERITORS_SELECTOR, UtSettings.pathSelectorType)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/utbot-analytics/src/test/resources/corrupted_nn.json b/utbot-analytics/src/test/resources/corrupted_nn.json
new file mode 100644
index 0000000000..ffc3ef7976
--- /dev/null
+++ b/utbot-analytics/src/test/resources/corrupted_nn.json
@@ -0,0 +1,25 @@
+{
+ dsfds
+ "linearLayers": [
+ [
+ [1, 0],
+ [0, 1]
+ ],
+ [
+ [1, 0],
+ [0, 1]
+ ],
+ [
+ [1, 1]
+ ]
+ ],
+ "activationLayers": [
+ "reLU",
+ "reLU"
+ ],
+ "biases": [
+ [1, 1],
+ [1, 1],
+ [1]
+ ]
+}
\ No newline at end of file
diff --git a/utbot-analytics/src/test/resources/corrupted_scaler.txt b/utbot-analytics/src/test/resources/corrupted_scaler.txt
new file mode 100644
index 0000000000..42ff95f905
--- /dev/null
+++ b/utbot-analytics/src/test/resources/corrupted_scaler.txt
@@ -0,0 +1 @@
+1,asada
\ No newline at end of file
diff --git a/utbot-analytics/src/test/resources/empty_nn.json b/utbot-analytics/src/test/resources/empty_nn.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/utbot-analytics/src/test/resources/linear.txt b/utbot-analytics/src/test/resources/linear.txt
new file mode 100644
index 0000000000..8a6627b46a
--- /dev/null
+++ b/utbot-analytics/src/test/resources/linear.txt
@@ -0,0 +1 @@
+1,1,1
\ No newline at end of file
diff --git a/utbot-analytics/src/test/resources/nn.json b/utbot-analytics/src/test/resources/nn.json
new file mode 100644
index 0000000000..945b53aef8
--- /dev/null
+++ b/utbot-analytics/src/test/resources/nn.json
@@ -0,0 +1,24 @@
+{
+ "linearLayers": [
+ [
+ [1, 0],
+ [0, 1]
+ ],
+ [
+ [1, 0],
+ [0, 1]
+ ],
+ [
+ [1, 1]
+ ]
+ ],
+ "activationLayers": [
+ "reLU",
+ "reLU"
+ ],
+ "biases": [
+ [1, 1],
+ [1, 1],
+ [1]
+ ]
+}
\ No newline at end of file
diff --git a/utbot-analytics/src/test/resources/scaler.txt b/utbot-analytics/src/test/resources/scaler.txt
new file mode 100644
index 0000000000..b241d25f33
--- /dev/null
+++ b/utbot-analytics/src/test/resources/scaler.txt
@@ -0,0 +1,2 @@
+0,0
+1,1
diff --git a/utbot-analytics/src/test/resources/wrong_format_linear.txt b/utbot-analytics/src/test/resources/wrong_format_linear.txt
new file mode 100644
index 0000000000..bf4d5a1b19
--- /dev/null
+++ b/utbot-analytics/src/test/resources/wrong_format_linear.txt
@@ -0,0 +1 @@
+1,asdasdsa,asdasd
\ No newline at end of file
diff --git a/utbot-api/build.gradle b/utbot-api/build.gradle
index fc50f68057..e99e0d7078 100644
--- a/utbot-api/build.gradle
+++ b/utbot-api/build.gradle
@@ -1 +1,11 @@
+plugins {
+ id "com.github.johnrengelman.shadow" version "6.1.0"
+}
+
apply from: "${parent.projectDir}/gradle/include/jvm-project.gradle"
+
+shadowJar {
+ configurations = [project.configurations.compileClasspath]
+ archiveClassifier.set('')
+ minimize()
+}
\ No newline at end of file
diff --git a/utbot-api/src/main/java/org/utbot/api/mock/UtMock.java b/utbot-api/src/main/java/org/utbot/api/mock/UtMock.java
index 1b7b512dfb..c7f7b2215b 100644
--- a/utbot-api/src/main/java/org/utbot/api/mock/UtMock.java
+++ b/utbot-api/src/main/java/org/utbot/api/mock/UtMock.java
@@ -13,6 +13,14 @@ public static T makeSymbolic(boolean isNullable) {
@SuppressWarnings("unused")
public static void assume(boolean predicate) {
// to use compilers checks, i.e. for possible NPE
- if (!predicate) throw new RuntimeException();
+ if (!predicate) {
+ throw new RuntimeException();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public static void assumeOrExecuteConcretely(boolean predicate) {
+ // In oppose to assume, we don't have predicate check here
+ // to avoid RuntimeException during concrete execution
}
}
\ No newline at end of file
diff --git a/utbot-cli/build.gradle b/utbot-cli/build.gradle
index 0f9d0bec4d..9e2106f3e7 100644
--- a/utbot-cli/build.gradle
+++ b/utbot-cli/build.gradle
@@ -1,15 +1,17 @@
apply from: "${parent.projectDir}/gradle/include/jvm-project.gradle"
+configurations {
+ fetchInstrumentationJar
+}
+
compileKotlin {
kotlinOptions {
allWarningsAsErrors = false
}
}
-
dependencies {
api project(":utbot-framework")
- api project(":utbot-analytics")
api project(':utbot-summary')
implementation group: 'org.mockito', name: 'mockito-core', version: mockito_version
@@ -25,6 +27,13 @@ dependencies {
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: log4j2_version
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: log4j2_version
implementation group: 'org.jacoco', name: 'org.jacoco.report', version: jacoco_version
+ fetchInstrumentationJar project(path: ':utbot-instrumentation', configuration:'instrumentationArchive')
+}
+
+processResources {
+ from(configurations.fetchInstrumentationJar) {
+ into "lib"
+ }
}
task createProperties(dependsOn: processResources) {
@@ -58,3 +67,4 @@ jar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
+
diff --git a/utbot-cli/src/main/kotlin/org/utbot/cli/GenerateTestsCommand.kt b/utbot-cli/src/main/kotlin/org/utbot/cli/GenerateTestsCommand.kt
index d54288ea25..0380efaa7b 100644
--- a/utbot-cli/src/main/kotlin/org/utbot/cli/GenerateTestsCommand.kt
+++ b/utbot-cli/src/main/kotlin/org/utbot/cli/GenerateTestsCommand.kt
@@ -94,6 +94,9 @@ class GenerateTestsCommand :
val targetMethods = classUnderTest.targetMethods()
initializeEngine(workingDirectory)
+ if (targetMethods.isEmpty()) {
+ throw Exception("Nothing to process. No methods were provided")
+ }
// utContext is used in `generateTestCases`, `generateTest`, `generateReport`
withUtContext(UtContext(targetMethods.first().clazz.java.classLoader)) {
diff --git a/utbot-core/build.gradle b/utbot-core/build.gradle
index f70ab1014f..271a7a5651 100644
--- a/utbot-core/build.gradle
+++ b/utbot-core/build.gradle
@@ -1,6 +1,16 @@
+plugins {
+ id "com.github.johnrengelman.shadow" version "6.1.0"
+}
+
apply from: "${parent.projectDir}/gradle/include/jvm-project.gradle"
dependencies {
implementation group: 'io.github.microutils', name: 'kotlin-logging', version: kotlin_logging_version
implementation group: 'net.java.dev.jna', name: 'jna-platform', version: '5.5.0'
}
+
+shadowJar {
+ configurations = [project.configurations.compileClasspath]
+ archiveClassifier.set('')
+ minimize()
+}
\ No newline at end of file
diff --git a/utbot-core/src/main/kotlin/org/utbot/common/FileUtil.kt b/utbot-core/src/main/kotlin/org/utbot/common/FileUtil.kt
index 77f007eda1..cab4e7ff33 100644
--- a/utbot-core/src/main/kotlin/org/utbot/common/FileUtil.kt
+++ b/utbot-core/src/main/kotlin/org/utbot/common/FileUtil.kt
@@ -75,12 +75,8 @@ object FileUtil {
}.forEach { it.deleteRecursively() }
}
- private fun createTempDirectory(): Path {
- val tempFolderPath = Paths.get(tempDirectoryPath + File.separator + utBotTempFolderPrefix)
-
- tempFolderPath.toFile().mkdirs()
-
- return createTempDirectory(tempFolderPath, "generated-")
+ fun createTempDirectory(prefix: String): Path {
+ return createTempDirectory(utBotTempDirectory, prefix)
}
/**
@@ -88,7 +84,7 @@ object FileUtil {
* It can be used for Soot analysis.
*/
fun isolateClassFiles(vararg classes: KClass<*>): File {
- val tempDir = createTempDirectory().toFile()
+ val tempDir = createTempDirectory("generated-").toFile()
for (clazz in classes) {
val path = clazz.toClassFilePath()
diff --git a/utbot-core/src/main/kotlin/org/utbot/common/KClassUtil.kt b/utbot-core/src/main/kotlin/org/utbot/common/KClassUtil.kt
index 7c8572d0d5..1f6bb848a5 100644
--- a/utbot-core/src/main/kotlin/org/utbot/common/KClassUtil.kt
+++ b/utbot-core/src/main/kotlin/org/utbot/common/KClassUtil.kt
@@ -28,4 +28,4 @@ fun Method.invokeCatching(obj: Any?, args: List) = try {
Result.success(invoke(obj, *args.toTypedArray()))
} catch (e: InvocationTargetException) {
Result.failure(e.targetException)
-}
\ No newline at end of file
+}
diff --git a/utbot-framework-api/build.gradle b/utbot-framework-api/build.gradle
index 96a133dcad..d922375eef 100644
--- a/utbot-framework-api/build.gradle
+++ b/utbot-framework-api/build.gradle
@@ -1,5 +1,8 @@
-apply from: "${parent.projectDir}/gradle/include/jvm-project.gradle"
+plugins {
+ id "com.github.johnrengelman.shadow" version "6.1.0"
+}
+apply from: "${parent.projectDir}/gradle/include/jvm-project.gradle"
dependencies {
api project(':utbot-core')
@@ -9,4 +12,10 @@ dependencies {
// TODO do we really need apache commons?
implementation group: 'org.apache.commons', name: 'commons-lang3', version: commons_lang_version
implementation group: 'io.github.microutils', name: 'kotlin-logging', version: kotlin_logging_version
+}
+
+shadowJar {
+ configurations = [project.configurations.compileClasspath]
+ archiveClassifier.set('')
+ minimize()
}
\ No newline at end of file
diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt
index b97d534627..6eee9a2d39 100644
--- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt
+++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt
@@ -1,14 +1,12 @@
package org.utbot.framework
+import mu.KotlinLogging
import org.utbot.common.PathUtil.toPath
import java.io.FileInputStream
-import java.io.FileNotFoundException
import java.io.IOException
import java.util.Properties
-import kotlin.io.path.exists
import kotlin.properties.PropertyDelegateProvider
import kotlin.reflect.KProperty
-import mu.KotlinLogging
private val logger = KotlinLogging.logger {}
@@ -31,7 +29,7 @@ internal class SettingDelegate(val initializer: () -> T) {
/**
* Default concrete execution timeout (in milliseconds).
*/
-const val DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS = 100L
+const val DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS = 1000L
object UtSettings {
private val properties = Properties().also { props ->
@@ -70,7 +68,8 @@ object UtSettings {
private fun getIntProperty(defaultValue: Int) = getProperty(defaultValue, String::toInt)
private fun getLongProperty(defaultValue: Long) = getProperty(defaultValue, String::toLong)
private fun getStringProperty(defaultValue: String) = getProperty(defaultValue) { it }
- private inline fun > getEnumProperty(defaultValue: T) = getProperty(defaultValue) { enumValueOf(it) }
+ private inline fun > getEnumProperty(defaultValue: T) =
+ getProperty(defaultValue) { enumValueOf(it) }
/**
@@ -110,6 +109,16 @@ object UtSettings {
*/
var pathSelectorType: PathSelectorType by getEnumProperty(PathSelectorType.INHERITORS_SELECTOR)
+ /**
+ * Type of nnRewardGuidedSelector
+ */
+ var nnRewardGuidedSelectorType: NNRewardGuidedSelectorType by getEnumProperty(NNRewardGuidedSelectorType.WITHOUT_RECALCULATION)
+
+ /**
+ * Type of [StateRewardPredictor]
+ */
+ var stateRewardPredictorType: StateRewardPredictorType by getEnumProperty(StateRewardPredictorType.BASE)
+
/**
* Steps limit for path selector.
*/
@@ -154,7 +163,7 @@ object UtSettings {
/*
* Activate or deactivate tests on comments && names/displayNames
* */
- var testSummary by getBooleanProperty( true)
+ var testSummary by getBooleanProperty(true)
var testName by getBooleanProperty(true)
var testDisplayName by getBooleanProperty(true)
@@ -237,7 +246,17 @@ object UtSettings {
/**
* Set to true to start fuzzing if symbolic execution haven't return anything
*/
- var useFuzzing: Boolean by getBooleanProperty(false)
+ var useFuzzing: Boolean by getBooleanProperty(true)
+
+ /**
+ * Set the total attempts to improve coverage by fuzzer.
+ */
+ var fuzzingMaxAttempts: Int by getIntProperty(Int.MAX_VALUE)
+
+ /**
+ * Fuzzer tries to generate and run tests during this time.
+ */
+ var fuzzingTimeoutInMillis: Int by getIntProperty(3_000)
/**
* Generate tests that treat possible overflows in arithmetic operations as errors
@@ -261,7 +280,17 @@ object UtSettings {
/**
* Timeout for specific concrete execution (in milliseconds).
*/
- var concreteExecutionTimeoutInChildProcess: Long by getLongProperty(DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS)
+ var concreteExecutionTimeoutInChildProcess: Long by getLongProperty(
+ DEFAULT_CONCRETE_EXECUTION_TIMEOUT_IN_CHILD_PROCESS_MS
+ )
+
+ /**
+ * Determines whether should errors from a child process be written to a log file or suppressed.
+ * Note: being enabled, this option can highly increase disk usage when using ContestEstimator.
+ *
+ * False by default (for saving disk space).
+ */
+ var logConcreteExecutionErrors by getBooleanProperty(false)
/**
* Number of branch instructions using for clustering executions in the test minimization phase.
@@ -283,6 +312,55 @@ object UtSettings {
*/
var enableUnsatCoreCalculationForHardConstraints by getBooleanProperty(false)
+ /**
+ * Enable it to process states with unknown solver status
+ * from the queue to concrete execution.
+ *
+ * True by default.
+ */
+ var processUnknownStatesDuringConcreteExecution by getBooleanProperty(true)
+
+ /**
+ * 2^{this} will be the length of observed subpath.
+ * See [SubpathGuidedSelector]
+ */
+ var subpathGuidedSelectorIndex by getIntProperty(1)
+
+ /**
+ * Set of indexes, which will use [SubpathGuidedSelector] in not single mode
+ */
+ var subpathGuidedSelectorIndexes = listOf(0, 1, 2, 3)
+
+ /**
+ * Flag that indicates whether feature processing for execution states enabled or not
+ */
+ var enableFeatureProcess by getBooleanProperty(false)
+
+ /**
+ * Path to deserialized reward models
+ */
+ var rewardModelPath by getStringProperty("../models/0")
+
+ /**
+ * Number of model iterations that will be used during ContestEstimator
+ */
+ var iterations by getIntProperty(1)
+
+ /**
+ * Path for state features dir
+ */
+ var featurePath by getStringProperty("eval/secondFeatures/antlr/INHERITORS_SELECTOR")
+
+ /**
+ * Counter for tests during testGeneration for one project in ContestEstimator
+ */
+ var testCounter by getIntProperty(0)
+
+ /**
+ * Flag for Subpath and NN selectors whether they are combined (Subpath use several indexes, NN use several models)
+ */
+ var singleSelector by getBooleanProperty(true)
+
override fun toString(): String =
properties
.entries
@@ -290,12 +368,87 @@ object UtSettings {
.joinToString(separator = System.lineSeparator()) { "\t${it.key}=${it.value}" }
}
+/**
+ * Type of [BasePathSelector]. For each value see class in comment
+ */
enum class PathSelectorType {
+ /**
+ * [CoveredNewSelector]
+ */
COVERED_NEW_SELECTOR,
- INHERITORS_SELECTOR
+
+ /**
+ * [InheritorsSelector]
+ */
+ INHERITORS_SELECTOR,
+
+ /**
+ * [SubpathGuidedSelector]
+ */
+ SUBPATH_GUIDED_SELECTOR,
+
+ /**
+ * [CPInstSelector]
+ */
+ CPI_SELECTOR,
+
+ /**
+ * [ForkDepthSelector]
+ */
+ FORK_DEPTH_SELECTOR,
+
+ /**
+ * [NNRewardGuidedSelector]
+ */
+ NN_REWARD_GUIDED_SELECTOR,
+
+ /**
+ * [RandomSelector]
+ */
+ RANDOM_SELECTOR,
+
+ /**
+ * [RandomPathSelector]
+ */
+ RANDOM_PATH_SELECTOR
}
enum class TestSelectionStrategyType {
DO_NOT_MINIMIZE_STRATEGY, // Always adds new test
COVERAGE_STRATEGY // Adds new test only if it increases coverage
}
+
+/**
+ * Enum to specify [NNRewardGuidedSelector], see implementations for more details
+ */
+enum class NNRewardGuidedSelectorType {
+ /**
+ * [NNRewardGuidedSelectorWithRecalculation]
+ */
+ WITH_RECALCULATION,
+
+ /**
+ * [NNRewardGuidedSelectorWithoutRecalculation]
+ */
+ WITHOUT_RECALCULATION
+}
+
+/**
+ * Enum to specify [StateRewardPredictor], see implementations for details
+ */
+enum class StateRewardPredictorType {
+ /**
+ * [NNStateRewardPredictorBase]
+ */
+ BASE,
+
+ /**
+ * [StateRewardPredictorTorch]
+ */
+ TORCH,
+
+ /**
+ * [NNStateRewardPredictorBase]
+ */
+ LINEAR
+}
diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt
index d67044b753..be42ca8e4b 100644
--- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt
+++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt
@@ -420,7 +420,7 @@ data class UtArrayModel(
override val id: Int,
override val classId: ClassId,
val length: Int = 0,
- val constModel: UtModel,
+ var constModel: UtModel,
val stores: MutableMap
) : UtReferenceModel(id, classId) {
override fun toString() = withToStringThreadLocalReentrancyGuard {
@@ -653,6 +653,9 @@ open class ClassId(
open val packageName: String get() = jClass.`package`?.name ?: "" // empty package for primitives
+ open val isInDefaultPackage: Boolean
+ get() = packageName.isEmpty()
+
open val isPublic: Boolean
get() = Modifier.isPublic(jClass.modifiers)
@@ -1041,7 +1044,7 @@ enum class MockStrategyApi(
override val displayName: String,
override val description: String
) : CodeGenerationSettingItem {
- NO_MOCKS("No mocks", "Do not use Mock frameworks at all"),
+ NO_MOCKS("No mocks", "Do not use mock frameworks at all"),
OTHER_PACKAGES(
"Other packages: $MOCKITO",
"Mock all classes outside the current package except system ones"
@@ -1102,7 +1105,7 @@ enum class MockFramework(
enum class CodegenLanguage(
override val displayName: String,
- @Suppress("unused") override val description: String = "Generating unit tests in $displayName"
+ @Suppress("unused") override val description: String = "Generate unit tests in $displayName"
) : CodeGenerationSettingItem {
JAVA(displayName = "Java"),
KOTLIN(displayName = "Kotlin");
@@ -1155,6 +1158,9 @@ enum class CodegenLanguage(
).plus(sourcesFiles)
KOTLIN -> listOf("-d", buildDirectory, "-jvm-target", jvmTarget, "-cp", classPath).plus(sourcesFiles)
}
+ if (this == KOTLIN && System.getenv("KOTLIN_HOME") == null) {
+ throw RuntimeException("'KOTLIN_HOME' environment variable is not defined. Standard location is {IDEA installation dir}/plugins/Kotlin/kotlinc")
+ }
return listOf(compilerExecutableAbsolutePath) + isolateCommandLineArgumentsToArgumentFile(arguments)
}
diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/impl/FieldIdStrategies.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/impl/FieldIdStrategies.kt
index a29a58c026..8ce32fdbc2 100644
--- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/impl/FieldIdStrategies.kt
+++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/impl/FieldIdStrategies.kt
@@ -47,7 +47,7 @@ class FieldIdReflectionStrategy(val fieldId: FieldId) : FieldIdStrategy {
get() = Modifier.isStatic(fieldId.field.modifiers)
override val isSynthetic: Boolean
- get() = false
+ get() = fieldId.field.isSynthetic
override val type: ClassId
get() = fieldId.field.type.id
diff --git a/utbot-framework/build.gradle b/utbot-framework/build.gradle
index a558f2daf5..98a734f37b 100644
--- a/utbot-framework/build.gradle
+++ b/utbot-framework/build.gradle
@@ -8,20 +8,18 @@ repositories {
configurations {
z3native
- fetchInstrumentationJar
}
dependencies {
- fetchInstrumentationJar project(path: ':utbot-instrumentation', configuration:'instrumentationArchive')
api project(':utbot-core')
+ api project(':utbot-instrumentation')
+ api project(':utbot-summary')
implementation 'junit:junit:4.13.1'
api project(':utbot-framework-api')
implementation "com.github.UnitTestBot:soot:${soot_commit_hash}"
- api group: 'com.google.guava', name: 'guava', version: guava_version
-
implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: jackson_version
implementation group: 'org.sosy-lab', name: 'javasmt-solver-z3', version: javasmt_solver_z3_version
implementation group: 'com.github.curious-odd-man', name: 'rgxgen', version: rgxgen_version
@@ -32,7 +30,6 @@ dependencies {
// we need this for construction mocks from composite models
implementation group: 'org.mockito', name: 'mockito-core', version: '4.2.0'
api project(':utbot-api')
- api project(':utbot-instrumentation')
api project(':utbot-fuzzers')
testImplementation project(':utbot-summary')
@@ -47,12 +44,14 @@ dependencies {
testImplementation group: 'org.mockito', name: 'mockito-core', version: mockito_version
testImplementation group: 'org.testng', name: 'testng', version: testng_version
testImplementation group: 'org.mockito', name: 'mockito-inline', version: mockito_inline_version
+ testImplementation group: 'com.google.guava', name: 'guava', version: guava_version
testCompile group: 'org.mockito', name: 'mockito-inline', version: mockito_inline_version
testCompile group: 'org.apache.logging.log4j', name: 'log4j-core', version: log4j2_version
z3native group: 'com.microsoft.z3', name: 'z3-native-win64', version: z3_version, ext: 'zip'
z3native group: 'com.microsoft.z3', name: 'z3-native-linux64', version: z3_version, ext: 'zip'
+ z3native group: 'com.microsoft.z3', name: 'z3-native-osx', version: z3_version, ext: 'zip'
}
processResources {
@@ -61,15 +60,10 @@ processResources {
into "lib/x64"
}
}
-
- // We will extract this jar in `ChildProcessRunner` class.
- from(configurations.fetchInstrumentationJar) {
- into "instrumentation-lib"
- }
}
test {
if (System.getProperty('DEBUG', 'false') == 'true') {
jvmArgs '-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9009'
}
-}
\ No newline at end of file
+}
diff --git a/utbot-framework/dist/z3-native-osx-4.8.9.1.zip b/utbot-framework/dist/z3-native-osx-4.8.9.1.zip
new file mode 100644
index 0000000000..9b42561fc9
Binary files /dev/null and b/utbot-framework/dist/z3-native-osx-4.8.9.1.zip differ
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/Byte.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/Byte.java
index e4e9c8b342..2b34640b25 100644
--- a/utbot-framework/src/main/java/org/utbot/engine/overrides/Byte.java
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/Byte.java
@@ -7,6 +7,7 @@
import static org.utbot.api.mock.UtMock.assume;
import static org.utbot.engine.overrides.UtLogicMock.ite;
+import static org.utbot.api.mock.UtMock.assumeOrExecuteConcretely;
import static org.utbot.engine.overrides.UtLogicMock.less;
import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;
@@ -34,7 +35,7 @@ public static byte parseByte(String s, int radix) {
if ((s.charAt(0) == '-' || s.charAt(0) == '+') && s.length() == 1) {
throw new NumberFormatException();
}
- assume(s.length() <= 10);
+ assumeOrExecuteConcretely(s.length() <= 10);
// we need two branches to add more options for concrete executor to find both branches
if (s.charAt(0) == '-') {
executeConcretely();
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/Integer.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/Integer.java
index 0c08c5d869..1142f01606 100644
--- a/utbot-framework/src/main/java/org/utbot/engine/overrides/Integer.java
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/Integer.java
@@ -5,7 +5,7 @@
import org.utbot.engine.overrides.strings.UtString;
import org.utbot.engine.overrides.strings.UtStringBuilder;
-import static org.utbot.api.mock.UtMock.assume;
+import static org.utbot.api.mock.UtMock.assumeOrExecuteConcretely;
import static org.utbot.engine.overrides.UtLogicMock.ite;
import static org.utbot.engine.overrides.UtLogicMock.less;
import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;
@@ -34,7 +34,7 @@ public static int parseInt(String s, int radix) {
if ((s.charAt(0) == '-' || s.charAt(0) == '+') && s.length() == 1) {
throw new NumberFormatException();
}
- assume(s.length() <= 10);
+ assumeOrExecuteConcretely(s.length() <= 10);
// we need two branches to add more options for concrete executor to find both branches
if (s.charAt(0) == '-') {
executeConcretely();
@@ -62,7 +62,7 @@ public static int parseUnsignedInt(String s, int radix) {
if ((s.charAt(0) == '-' || s.charAt(0) == '+') && s.length() == 1) {
throw new NumberFormatException();
}
- assume(s.length() <= 10);
+ assumeOrExecuteConcretely(s.length() <= 10);
if (s.charAt(0) == '-') {
throw new NumberFormatException();
} else {
@@ -77,8 +77,8 @@ public static String toString(int i) {
}
// assumes are placed here to limit search space of solver
// and reduce time of solving queries with bv2int expressions
- assume(i <= 0x8000);
- assume(i >= -0x8000);
+ assumeOrExecuteConcretely(i <= 0x8000);
+ assumeOrExecuteConcretely(i >= -0x8000);
// condition = i < 0
boolean condition = less(i, 0);
// prefix = condition ? "-" : ""
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/Long.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/Long.java
index 9b7a9fcdb5..4ee5283716 100644
--- a/utbot-framework/src/main/java/org/utbot/engine/overrides/Long.java
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/Long.java
@@ -5,7 +5,7 @@
import org.utbot.engine.overrides.strings.UtString;
import org.utbot.engine.overrides.strings.UtStringBuilder;
-import static org.utbot.api.mock.UtMock.assume;
+import static org.utbot.api.mock.UtMock.assumeOrExecuteConcretely;
import static org.utbot.engine.overrides.UtLogicMock.ite;
import static org.utbot.engine.overrides.UtLogicMock.less;
import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;
@@ -34,7 +34,7 @@ public static long parseLong(String s, int radix) {
if ((s.charAt(0) == '-' || s.charAt(0) == '+') && s.length() == 1) {
throw new NumberFormatException();
}
- assume(s.length() <= 10);
+ assumeOrExecuteConcretely(s.length() <= 10);
// we need two branches to add more options for concrete executor to find both branches
if (s.charAt(0) == '-') {
executeConcretely();
@@ -62,7 +62,7 @@ public static long parseUnsignedLong(String s, int radix) {
if ((s.charAt(0) == '-' || s.charAt(0) == '+') && s.length() == 1) {
throw new NumberFormatException();
}
- assume(s.length() <= 10);
+ assumeOrExecuteConcretely(s.length() <= 10);
if (s.charAt(0) == '-') {
throw new NumberFormatException();
} else {
@@ -77,8 +77,8 @@ public static String toString(long l) {
}
// assumes are placed here to limit search space of solver
// and reduce time of solving queries with bv2int expressions
- assume(l <= 10000);
- assume(l >= 10000);
+ assumeOrExecuteConcretely(l <= 10000);
+ assumeOrExecuteConcretely(l >= -10000);
// condition = l < 0
boolean condition = less(l, 0);
// prefix = condition ? "-" : ""
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/Short.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/Short.java
index af7263b898..d8b47fbaf3 100644
--- a/utbot-framework/src/main/java/org/utbot/engine/overrides/Short.java
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/Short.java
@@ -5,7 +5,7 @@
import org.utbot.engine.overrides.strings.UtString;
import org.utbot.engine.overrides.strings.UtStringBuilder;
-import static org.utbot.api.mock.UtMock.assume;
+import static org.utbot.api.mock.UtMock.assumeOrExecuteConcretely;
import static org.utbot.engine.overrides.UtLogicMock.ite;
import static org.utbot.engine.overrides.UtLogicMock.less;
import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;
@@ -34,7 +34,7 @@ public static java.lang.Short parseShort(String s, int radix) {
if ((s.charAt(0) == '-' || s.charAt(0) == '+') && s.length() == 1) {
throw new NumberFormatException();
}
- assume(s.length() <= 10);
+ assumeOrExecuteConcretely(s.length() <= 10);
// we need two branches to add more options for concrete executor to find both branches
if (s.charAt(0) == '-') {
executeConcretely();
@@ -50,8 +50,8 @@ public static String toString(short s) {
boolean condition = less(s, (short) 0);
// assumes are placed here to limit search space of solver
// and reduce time of solving queries with bv2int expressions
- assume(s <= 10000);
- assume(s >= 10000);
+ assumeOrExecuteConcretely(s <= 10000);
+ assumeOrExecuteConcretely(s >= -10000);
// prefix = condition ? "-" : ""
String prefix = ite(condition, "-", "");
UtStringBuilder sb = new UtStringBuilder(prefix);
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/AbstractCollection.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/AbstractCollection.java
new file mode 100644
index 0000000000..82ba954be4
--- /dev/null
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/AbstractCollection.java
@@ -0,0 +1,13 @@
+package org.utbot.engine.overrides.collections;
+
+import org.utbot.api.annotation.UtClassMock;
+
+import static org.utbot.api.mock.UtMock.makeSymbolic;
+
+@UtClassMock(target = java.util.AbstractCollection.class, internalUsage = true)
+public abstract class AbstractCollection implements java.util.Collection {
+ @Override
+ public String toString() {
+ return makeSymbolic();
+ }
+}
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/Collection.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/Collection.java
new file mode 100644
index 0000000000..8f7edebe37
--- /dev/null
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/Collection.java
@@ -0,0 +1,27 @@
+package org.utbot.engine.overrides.collections;
+
+import org.utbot.api.annotation.UtClassMock;
+import org.utbot.engine.overrides.stream.UtStream;
+
+import java.util.stream.Stream;
+
+@UtClassMock(target = java.util.Collection.class, internalUsage = true)
+public interface Collection extends java.util.Collection {
+ @SuppressWarnings("unchecked")
+ @Override
+ default Stream parallelStream() {
+ Object[] data = toArray();
+ int size = data.length;
+
+ return new UtStream<>((E[]) data, size);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ default Stream stream() {
+ Object[] data = toArray();
+ int size = data.length;
+
+ return new UtStream<>((E[]) data, size);
+ }
+}
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/List.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/List.java
new file mode 100644
index 0000000000..b04c16694b
--- /dev/null
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/List.java
@@ -0,0 +1,72 @@
+package org.utbot.engine.overrides.collections;
+
+import org.utbot.api.annotation.UtClassMock;
+
+import java.util.Collection;
+
+@UtClassMock(target = java.util.List.class, internalUsage = true)
+public interface List extends java.util.List {
+ static java.util.List of() {
+ return new UtArrayList<>();
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.List of(E e1) {
+ return new UtArrayList<>((E[]) new Object[]{e1});
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.List of(E e1, E e2) {
+ return new UtArrayList<>((E[]) new Object[]{e1, e2});
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.List of(E e1, E e2, E e3) {
+ return new UtArrayList<>((E[]) new Object[]{e1, e2, e3});
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.List of(E e1, E e2, E e3, E e4) {
+ return new UtArrayList<>((E[]) new Object[]{e1, e2, e3, e4});
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.List of(E e1, E e2, E e3, E e4, E e5) {
+ return new UtArrayList<>((E[]) new Object[]{e1, e2, e3, e4, e5});
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.List of(E e1, E e2, E e3, E e4, E e5, E e6) {
+ return new UtArrayList<>((E[]) new Object[]{e1, e2, e3, e4, e5, e6});
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
+ return new UtArrayList<>((E[]) new Object[]{e1, e2, e3, e4, e5, e6, e7});
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
+ return new UtArrayList<>((E[]) new Object[]{e1, e2, e3, e4, e5, e6, e7, e8});
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
+ return new UtArrayList<>((E[]) new Object[]{e1, e2, e3, e4, e5, e6, e7, e8, e9});
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
+ return new UtArrayList<>((E[]) new Object[]{e1, e2, e3, e4, e5, e6, e7, e8, e9, e10});
+ }
+
+ @SafeVarargs
+ @SuppressWarnings("varargs")
+ static java.util.List of(E... elements) {
+ return new UtArrayList<>(elements);
+ }
+
+ static java.util.List copyOf(Collection extends E> collection) {
+ return new UtArrayList<>(collection);
+ }
+}
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtArrayList.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtArrayList.java
index 365c6d52c3..5db94b3fb7 100644
--- a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtArrayList.java
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtArrayList.java
@@ -13,9 +13,13 @@
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
+import java.util.stream.Stream;
+
import org.jetbrains.annotations.NotNull;
+import org.utbot.engine.overrides.stream.UtStream;
import static org.utbot.api.mock.UtMock.assume;
+import static org.utbot.api.mock.UtMock.assumeOrExecuteConcretely;
import static org.utbot.engine.ResolverKt.MAX_LIST_SIZE;
import static org.utbot.engine.overrides.UtOverrideMock.alreadyVisited;
import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;
@@ -59,6 +63,14 @@ public UtArrayList(Collection extends E> c) {
addAll(c);
}
+ public UtArrayList(E[] data) {
+ visit(this);
+ int length = data.length;
+ elementData = new RangeModifiableUnlimitedArray<>();
+ elementData.setRange(0, data, 0, length);
+ elementData.end = length;
+ }
+
/**
* Precondition check is called only once by object,
* if it was passed as parameter to method under test.
@@ -82,7 +94,8 @@ void preconditionCheck() {
int size = elementData.end;
assume(elementData.begin == 0);
- assume(size >= 0 & size <= MAX_LIST_SIZE);
+ assume(size >= 0);
+ assumeOrExecuteConcretely(size <= MAX_LIST_SIZE);
visit(this);
}
@@ -359,6 +372,28 @@ public void replaceAll(UnaryOperator operator) {
}
}
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream stream() {
+ preconditionCheck();
+
+ int size = elementData.end;
+ Object[] data = elementData.toArray(0, size);
+
+ return new UtStream<>((E[]) data, size);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream parallelStream() {
+ preconditionCheck();
+
+ int size = elementData.end;
+ Object[] data = elementData.toArray(0, size);
+
+ return new UtStream<>((E[]) data, size);
+ }
+
/**
* Auxiliary method, that should be only executed concretely
* @return new ArrayList with all the elements from this.
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtHashMap.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtHashMap.java
index 8e8e296493..57aba7f5c4 100644
--- a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtHashMap.java
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtHashMap.java
@@ -15,9 +15,9 @@
import org.jetbrains.annotations.Nullable;
import static org.utbot.api.mock.UtMock.assume;
+import static org.utbot.api.mock.UtMock.makeSymbolic;
import static org.utbot.engine.overrides.UtOverrideMock.alreadyVisited;
import static org.utbot.engine.overrides.UtOverrideMock.doesntThrow;
-import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;
import static org.utbot.engine.overrides.UtOverrideMock.parameter;
import static org.utbot.engine.overrides.UtOverrideMock.visit;
@@ -100,12 +100,12 @@ void preconditionCheck() {
parameter(values.touched);
parameter(values.storage);
parameter(keys);
- // for some unknown reason parameter(keys.storage) leads to MapValuesTest::testIteratorNext test failure
+ parameter(keys.storage);
assume(values.size == keys.end);
assume(values.touched.length == keys.end);
doesntThrow();
- for (int i = 0; i < keys.end; i++) {
+ for (int i = keys.begin; i < keys.end; i++) {
K key = keys.get(i);
assume(values.touched[i] == key);
@@ -556,8 +556,7 @@ public final boolean remove(Object o) {
// TODO rewrite it JIRA:1604
@Override
public String toString() {
- executeConcretely();
- return super.toString();
+ return makeSymbolic();
}
public final class Entry implements Map.Entry {
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtHashSet.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtHashSet.java
index 744a1b5f15..69dd700e22 100644
--- a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtHashSet.java
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtHashSet.java
@@ -8,7 +8,10 @@
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
+import java.util.stream.Stream;
+
import org.jetbrains.annotations.NotNull;
+import org.utbot.engine.overrides.stream.UtStream;
import static org.utbot.api.mock.UtMock.assume;
import static org.utbot.engine.overrides.UtOverrideMock.alreadyVisited;
@@ -73,7 +76,7 @@ void preconditionCheck() {
doesntThrow();
// check that all elements are distinct.
- for (int i = 0; i < elementData.end; i++) {
+ for (int i = elementData.begin; i < elementData.end; i++) {
E element = elementData.get(i);
parameter(element);
// make element address non-positive
@@ -263,6 +266,28 @@ public Iterator iterator() {
return new UtHashSetIterator();
}
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream stream() {
+ preconditionCheck();
+
+ int size = elementData.end;
+ Object[] data = elementData.toArray(0, size);
+
+ return new UtStream<>((E[]) data, size);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream parallelStream() {
+ preconditionCheck();
+
+ int size = elementData.end;
+ Object[] data = elementData.toArray(0, size);
+
+ return new UtStream<>((E[]) data, size);
+ }
+
public class UtHashSetIterator implements Iterator {
int index = 0;
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtLinkedList.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtLinkedList.java
index 1e6be282dc..55a577cb52 100644
--- a/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtLinkedList.java
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/collections/UtLinkedList.java
@@ -13,12 +13,16 @@
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
+import java.util.stream.Stream;
+
import org.jetbrains.annotations.NotNull;
+import org.utbot.engine.overrides.stream.UtStream;
import static org.utbot.api.mock.UtMock.assume;
import static org.utbot.engine.ResolverKt.MAX_LIST_SIZE;
import static org.utbot.engine.overrides.UtOverrideMock.alreadyVisited;
import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;
+import static org.utbot.api.mock.UtMock.assumeOrExecuteConcretely;
import static org.utbot.engine.overrides.UtOverrideMock.parameter;
import static org.utbot.engine.overrides.UtOverrideMock.visit;
@@ -78,7 +82,8 @@ private void preconditionCheck() {
parameter(elementData);
parameter(elementData.storage);
assume(elementData.begin == 0);
- assume(elementData.end >= 0 & elementData.end <= MAX_LIST_SIZE);
+ assume(elementData.end >= 0);
+ assumeOrExecuteConcretely(elementData.end <= MAX_LIST_SIZE);
visit(this);
}
@@ -446,6 +451,29 @@ public Iterator descendingIterator() {
preconditionCheck();
return new ReverseIteratorWrapper(elementData.end);
}
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream stream() {
+ preconditionCheck();
+
+ int size = elementData.end;
+ Object[] data = elementData.toArray(0, size);
+
+ return new UtStream<>((E[]) data, size);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream parallelStream() {
+ preconditionCheck();
+
+ int size = elementData.end;
+ Object[] data = elementData.toArray(0, size);
+
+ return new UtStream<>((E[]) data, size);
+ }
+
public class ReverseIteratorWrapper implements ListIterator {
int index;
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/stream/Arrays.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/stream/Arrays.java
new file mode 100644
index 0000000000..9534452ff9
--- /dev/null
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/stream/Arrays.java
@@ -0,0 +1,29 @@
+package org.utbot.engine.overrides.stream;
+
+import org.utbot.api.annotation.UtClassMock;
+import org.utbot.engine.overrides.collections.UtArrayList;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+@UtClassMock(target = java.util.Arrays.class, internalUsage = true)
+public class Arrays {
+ public static Stream stream(T[] array, int startInclusive, int endExclusive) {
+ int size = array.length;
+
+ if (startInclusive < 0 || endExclusive < startInclusive || endExclusive > size) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ return new UtStream<>(array, startInclusive, endExclusive);
+ }
+
+ @SuppressWarnings({"unused", "varargs"})
+ @SafeVarargs
+ public static List asList(T... a) {
+ // TODO immutable collection https://github.com/UnitTestBot/UTBotJava/issues/398
+ return new UtArrayList<>(a);
+ }
+
+ // TODO primitive arrays https://github.com/UnitTestBot/UTBotJava/issues/146
+}
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/stream/Stream.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/stream/Stream.java
new file mode 100644
index 0000000000..cf9b533a4d
--- /dev/null
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/stream/Stream.java
@@ -0,0 +1,54 @@
+package org.utbot.engine.overrides.stream;
+
+import org.utbot.api.annotation.UtClassMock;
+
+import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
+import java.util.stream.BaseStream;
+
+import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;
+
+@SuppressWarnings("unused")
+@UtClassMock(target = java.util.stream.Stream.class, internalUsage = true)
+public interface Stream extends BaseStream> {
+ @SuppressWarnings("unchecked")
+ static java.util.stream.Stream of(E element) {
+ Object[] data = new Object[1];
+ data[0] = element;
+
+ return new UtStream<>((E[]) data, 1);
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.stream.Stream of(E... elements) {
+ int size = elements.length;
+
+ return new UtStream<>(elements, size);
+ }
+
+ @SuppressWarnings("unchecked")
+ static java.util.stream.Stream empty() {
+ return new UtStream<>((E[]) new Object[]{}, 0);
+ }
+
+ static java.util.stream.Stream generate(Supplier s) {
+ // as "generate" method produces an infinite stream, we cannot analyze it symbolically
+ executeConcretely();
+ return null;
+ }
+
+ static java.util.stream.Stream iterate(final E seed, final UnaryOperator f) {
+ // as "iterate" method produces an infinite stream, we cannot analyze it symbolically
+ executeConcretely();
+ return null;
+ }
+
+ static java.util.stream.Stream concat(
+ java.util.stream.Stream extends E> a,
+ java.util.stream.Stream extends E> b
+ ) {
+ // as provided streams might be infinite, we cannot analyze this method symbolically
+ executeConcretely();
+ return null;
+ }
+}
diff --git a/utbot-framework/src/main/java/org/utbot/engine/overrides/stream/UtStream.java b/utbot-framework/src/main/java/org/utbot/engine/overrides/stream/UtStream.java
new file mode 100644
index 0000000000..790a7ef16e
--- /dev/null
+++ b/utbot-framework/src/main/java/org/utbot/engine/overrides/stream/UtStream.java
@@ -0,0 +1,689 @@
+package org.utbot.engine.overrides.stream;
+
+import org.utbot.engine.overrides.UtArrayMock;
+import org.utbot.engine.overrides.collections.RangeModifiableUnlimitedArray;
+import org.utbot.engine.overrides.collections.UtGenericStorage;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.BinaryOperator;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.function.ToDoubleFunction;
+import java.util.function.ToIntFunction;
+import java.util.function.ToLongFunction;
+import java.util.stream.Collector;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+import org.jetbrains.annotations.NotNull;
+
+import static org.utbot.api.mock.UtMock.assume;
+import static org.utbot.api.mock.UtMock.assumeOrExecuteConcretely;
+import static org.utbot.engine.ResolverKt.HARD_MAX_ARRAY_SIZE;
+import static org.utbot.engine.overrides.UtOverrideMock.alreadyVisited;
+import static org.utbot.engine.overrides.UtOverrideMock.executeConcretely;
+import static org.utbot.engine.overrides.UtOverrideMock.parameter;
+import static org.utbot.engine.overrides.UtOverrideMock.visit;
+
+public class UtStream implements Stream, UtGenericStorage {
+ private final RangeModifiableUnlimitedArray elementData;
+
+ private final RangeModifiableUnlimitedArray closeHandlers = new RangeModifiableUnlimitedArray<>();
+
+ private boolean isParallel = false;
+
+ /**
+ * {@code false} by default, assigned to {@code true} after performing any operation on this stream. Any operation,
+ * performed on a closed UtStream, throws the {@link IllegalStateException}.
+ */
+ private boolean isClosed = false;
+
+ public UtStream() {
+ visit(this);
+ elementData = new RangeModifiableUnlimitedArray<>();
+ }
+
+ public UtStream(E[] data, int length) {
+ visit(this);
+ elementData = new RangeModifiableUnlimitedArray<>();
+ elementData.setRange(0, data, 0, length);
+ elementData.end = length;
+ }
+
+ public UtStream(E[] data, int startInclusive, int endExclusive) {
+ visit(this);
+
+ int size = endExclusive - startInclusive;
+
+ elementData = new RangeModifiableUnlimitedArray<>();
+ elementData.setRange(0, data, startInclusive, size);
+ elementData.end = size;
+ }
+
+ /**
+ * Precondition check is called only once by object,
+ * if it was passed as parameter to method under test.
+ *
+ * Preconditions that are must be satisfied:
+ *
elementData.size in 0..HARD_MAX_ARRAY_SIZE.
+ * elementData is marked as parameter
+ * elementData.storage and it's elements are marked as parameters
+ */
+ @SuppressWarnings("DuplicatedCode")
+ void preconditionCheck() {
+ if (alreadyVisited(this)) {
+ return;
+ }
+ setEqualGenericType(elementData);
+
+ assume(elementData != null);
+ assume(elementData.storage != null);
+
+ parameter(elementData);
+ parameter(elementData.storage);
+
+ assume(elementData.begin == 0);
+
+ assume(elementData.end >= 0);
+ // we can create a stream for an array using Stream.of
+ assume(elementData.end <= HARD_MAX_ARRAY_SIZE);
+
+ visit(this);
+ }
+
+ private void preconditionCheckWithClosingStream() {
+ preconditionCheck();
+
+ if (isClosed) {
+ throw new IllegalStateException();
+ }
+
+ // Even if exception occurs in the body of a stream operation, this stream could not be used later.
+ isClosed = true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream filter(Predicate super E> predicate) {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+ Object[] filtered = new Object[size];
+ int j = 0;
+ for (int i = 0; i < size; i++) {
+ E element = elementData.get(i);
+ if (predicate.test(element)) {
+ filtered[j++] = element;
+ }
+ }
+
+ return new UtStream<>((E[]) filtered, j);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream map(Function super E, ? extends R> mapper) {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+ Object[] mapped = new Object[size];
+ for (int i = 0; i < size; i++) {
+ mapped[i] = mapper.apply(elementData.get(i));
+ }
+
+ return new UtStream<>((R[]) mapped, size);
+ }
+
+ @Override
+ public IntStream mapToInt(ToIntFunction super E> mapper) {
+ preconditionCheckWithClosingStream();
+ // TODO https://github.com/UnitTestBot/UTBotJava/issues/146
+ executeConcretely();
+ return null;
+ }
+
+ @Override
+ public LongStream mapToLong(ToLongFunction super E> mapper) {
+ preconditionCheckWithClosingStream();
+ // TODO https://github.com/UnitTestBot/UTBotJava/issues/146
+ executeConcretely();
+ return null;
+ }
+
+ @Override
+ public DoubleStream mapToDouble(ToDoubleFunction super E> mapper) {
+ preconditionCheckWithClosingStream();
+ // TODO https://github.com/UnitTestBot/UTBotJava/issues/146
+ executeConcretely();
+ return null;
+ }
+
+ @Override
+ public Stream flatMap(Function super E, ? extends Stream extends R>> mapper) {
+ preconditionCheckWithClosingStream();
+ // as mapper can produce infinite streams, we cannot process it symbolically
+ executeConcretely();
+ return null;
+ }
+
+ @Override
+ public IntStream flatMapToInt(Function super E, ? extends IntStream> mapper) {
+ preconditionCheckWithClosingStream();
+ // TODO https://github.com/UnitTestBot/UTBotJava/issues/146
+ executeConcretely();
+ return null;
+ }
+
+ @Override
+ public LongStream flatMapToLong(Function super E, ? extends LongStream> mapper) {
+ preconditionCheckWithClosingStream();
+ // TODO https://github.com/UnitTestBot/UTBotJava/issues/146
+ executeConcretely();
+ return null;
+ }
+
+ @Override
+ public DoubleStream flatMapToDouble(Function super E, ? extends DoubleStream> mapper) {
+ preconditionCheckWithClosingStream();
+ // TODO https://github.com/UnitTestBot/UTBotJava/issues/146
+ executeConcretely();
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream distinct() {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+ Object[] distinctElements = new Object[size];
+ int distinctSize = 0;
+ for (int i = 0; i < size; i++) {
+ E element = elementData.get(i);
+ boolean isDuplicate = false;
+
+ if (element == null) {
+ for (int j = 0; j < distinctSize; j++) {
+ Object alreadyProcessedElement = distinctElements[j];
+ if (alreadyProcessedElement == null) {
+ isDuplicate = true;
+ break;
+ }
+ }
+ } else {
+ for (int j = 0; j < distinctSize; j++) {
+ Object alreadyProcessedElement = distinctElements[j];
+ if (element.equals(alreadyProcessedElement)) {
+ isDuplicate = true;
+ break;
+ }
+ }
+ }
+
+ if (!isDuplicate) {
+ distinctElements[distinctSize++] = element;
+ }
+ }
+
+ return new UtStream<>((E[]) distinctElements, distinctSize);
+ }
+
+ // TODO choose the best sorting https://github.com/UnitTestBot/UTBotJava/issues/188
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream sorted() {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+
+ if (size == 0) {
+ return new UtStream<>();
+ }
+
+ Object[] sortedElements = UtArrayMock.copyOf(elementData.toArray(0, size), size);
+
+ // bubble sort
+ for (int i = 0; i < size - 1; i++) {
+ for (int j = 0; j < size - i - 1; j++) {
+ if (((Comparable) sortedElements[j]).compareTo((E) sortedElements[j + 1]) > 0) {
+ Object tmp = sortedElements[j];
+ sortedElements[j] = sortedElements[j + 1];
+ sortedElements[j + 1] = tmp;
+ }
+ }
+ }
+
+ return new UtStream<>((E[]) sortedElements, size);
+ }
+
+ // TODO choose the best sorting https://github.com/UnitTestBot/UTBotJava/issues/188
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream sorted(Comparator super E> comparator) {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+
+ if (size == 0) {
+ return new UtStream<>();
+ }
+
+ Object[] sortedElements = UtArrayMock.copyOf(elementData.toArray(0, size), size);
+
+ // bubble sort
+ for (int i = 0; i < size - 1; i++) {
+ for (int j = 0; j < size - i - 1; j++) {
+ if (comparator.compare((E) sortedElements[j], (E) sortedElements[j + 1]) > 0) {
+ Object tmp = sortedElements[j];
+ sortedElements[j] = sortedElements[j + 1];
+ sortedElements[j + 1] = tmp;
+ }
+ }
+ }
+
+ return new UtStream<>((E[]) sortedElements, size);
+ }
+
+ @Override
+ public Stream peek(Consumer super E> action) {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+ for (int i = 0; i < size; i++) {
+ action.accept(elementData.get(i));
+ }
+
+ // returned stream should be opened, so we "reopen" this stream to return it
+ isClosed = false;
+
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream limit(long maxSize) {
+ preconditionCheckWithClosingStream();
+
+ if (maxSize < 0) {
+ throw new IllegalArgumentException();
+ }
+
+ assumeOrExecuteConcretely(maxSize <= Integer.MAX_VALUE);
+
+ int newSize = (int) maxSize;
+ int curSize = elementData.end;
+
+ if (newSize == curSize) {
+ return this;
+ }
+
+ if (newSize > curSize) {
+ newSize = curSize;
+ }
+
+ return new UtStream<>((E[]) elementData.toArray(0, newSize), newSize);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Stream skip(long n) {
+ preconditionCheckWithClosingStream();
+
+ if (n < 0) {
+ throw new IllegalArgumentException();
+ }
+
+ if (n == 0) {
+ return this;
+ }
+
+ int curSize = elementData.end;
+ if (n > curSize) {
+ return new UtStream<>();
+ }
+
+ // n is 1...Integer.MAX_VALUE here
+ int newSize = (int) (curSize - n);
+
+ return new UtStream<>((E[]) elementData.toArray((int) n, newSize), newSize);
+ }
+
+ @Override
+ public void forEach(Consumer super E> action) {
+ peek(action);
+ }
+
+ @Override
+ public void forEachOrdered(Consumer super E> action) {
+ peek(action);
+ }
+
+ @NotNull
+ @Override
+ public Object[] toArray() {
+ preconditionCheckWithClosingStream();
+
+ return elementData.toArray(0, elementData.end);
+ }
+
+ @NotNull
+ @Override
+ public A[] toArray(IntFunction generator) {
+ preconditionCheckWithClosingStream();
+
+ // TODO untracked ArrayStoreException - JIRA:1089
+ int size = elementData.end;
+ A[] array = generator.apply(size);
+
+ UtArrayMock.arraycopy(elementData.toArray(0, size), 0, array, 0, size);
+
+ return array;
+ }
+
+ @Override
+ public E reduce(E identity, BinaryOperator accumulator) {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+ E result = identity;
+ for (int i = 0; i < size; i++) {
+ result = accumulator.apply(result, elementData.get(i));
+ }
+
+ return result;
+ }
+
+ @SuppressWarnings("ConstantConditions")
+ @NotNull
+ @Override
+ public Optional reduce(BinaryOperator accumulator) {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+ if (size == 0) {
+ return Optional.empty();
+ }
+
+ E result = null;
+ for (int i = 0; i < size; i++) {
+ E element = elementData.get(i);
+ if (result == null) {
+ result = element;
+ } else {
+ result = accumulator.apply(result, element);
+ }
+ }
+
+ return Optional.of(result);
+ }
+
+ @Override
+ public U reduce(U identity, BiFunction accumulator, BinaryOperator combiner) {
+ preconditionCheckWithClosingStream();
+
+ // since this implementation is always sequential, we do not need to use the combiner
+ int size = elementData.end;
+ U result = identity;
+ for (int i = 0; i < size; i++) {
+ result = accumulator.apply(result, elementData.get(i));
+ }
+
+ return result;
+ }
+
+ @Override
+ public R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner) {
+ preconditionCheckWithClosingStream();
+
+ // since this implementation is always sequential, we do not need to use the combiner
+ int size = elementData.end;
+ R result = supplier.get();
+ for (int i = 0; i < size; i++) {
+ accumulator.accept(result, elementData.get(i));
+ }
+
+ return result;
+ }
+
+ @Override
+ public R collect(Collector super E, A, R> collector) {
+ preconditionCheckWithClosingStream();
+
+ // since this implementation is always sequential, we do not need to use the combiner
+ int size = elementData.end;
+ A result = collector.supplier().get();
+ for (int i = 0; i < size; i++) {
+ collector.accumulator().accept(result, elementData.get(i));
+ }
+
+ return collector.finisher().apply(result);
+ }
+
+ @NotNull
+ @Override
+ public Optional min(Comparator super E> comparator) {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+ if (size == 0) {
+ return Optional.empty();
+ }
+
+ E min = elementData.get(0);
+ for (int i = 1; i < size; i++) {
+ E element = elementData.get(i);
+ if (comparator.compare(min, element) > 0) {
+ min = element;
+ }
+ }
+
+ return Optional.of(min);
+ }
+
+ @NotNull
+ @Override
+ public Optional max(Comparator super E> comparator) {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+ if (size == 0) {
+ return Optional.empty();
+ }
+
+ E max = elementData.get(0);
+ for (int i = 1; i < size; i++) {
+ E element = elementData.get(i);
+ if (comparator.compare(max, element) < 0) {
+ max = element;
+ }
+ }
+
+ return Optional.of(max);
+ }
+
+ @Override
+ public long count() {
+ preconditionCheckWithClosingStream();
+
+ return elementData.end;
+ }
+
+ @Override
+ public boolean anyMatch(Predicate super E> predicate) {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+ for (int i = 0; i < size; i++) {
+ if (predicate.test(elementData.get(i))) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean allMatch(Predicate super E> predicate) {
+ preconditionCheckWithClosingStream();
+
+ int size = elementData.end;
+ for (int i = 0; i < size; i++) {
+ if (!predicate.test(elementData.get(i))) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean noneMatch(Predicate super E> predicate) {
+ preconditionCheckWithClosingStream();
+
+ return !anyMatch(predicate);
+ }
+
+ @NotNull
+ @Override
+ public Optional findFirst() {
+ preconditionCheckWithClosingStream();
+
+ if (elementData.end == 0) {
+ return Optional.empty();
+ }
+
+ E first = elementData.get(0);
+
+ return Optional.of(first);
+ }
+
+ @NotNull
+ @Override
+ public Optional findAny() {
+ preconditionCheckWithClosingStream();
+
+ // since this implementation is always sequential, we can just return the first element
+ return findFirst();
+ }
+
+ @NotNull
+ @Override
+ public Iterator iterator() {
+ preconditionCheckWithClosingStream();
+
+ return new UtStreamIterator(0);
+ }
+
+ @NotNull
+ @Override
+ public Spliterator spliterator() {
+ preconditionCheckWithClosingStream();
+ // implementation from AbstractList
+ return Spliterators.spliterator(elementData.toArray(0, elementData.end), Spliterator.ORDERED);
+ }
+
+ @Override
+ public boolean isParallel() {
+ // this method does not "close" this stream
+ preconditionCheck();
+
+ return isParallel;
+ }
+
+ @NotNull
+ @Override
+ public Stream sequential() {
+ // this method does not "close" this stream
+ preconditionCheck();
+
+ isParallel = false;
+
+ return this;
+ }
+
+ @NotNull
+ @Override
+ public Stream parallel() {
+ // this method does not "close" this stream
+ preconditionCheck();
+
+ isParallel = true;
+
+ return this;
+ }
+
+ @NotNull
+ @Override
+ public Stream unordered() {
+ // this method does not "close" this stream
+ preconditionCheck();
+
+ return this;
+ }
+
+ @NotNull
+ @Override
+ public Stream onClose(Runnable closeHandler) {
+ // this method does not "close" this stream
+ preconditionCheck();
+
+ // adds closeHandler to existing
+ closeHandlers.set(closeHandlers.end++, closeHandler);
+
+ return this;
+ }
+
+ @Override
+ public void close() {
+ // Stream can be closed via this method many times
+ preconditionCheck();
+
+ // TODO resources closing https://github.com/UnitTestBot/UTBotJava/issues/189
+
+ // NOTE: this implementation does not care about suppressing and throwing exceptions produced by handlers
+ for (int i = 0; i < closeHandlers.end; i++) {
+ closeHandlers.get(i).run();
+ }
+ }
+
+ public class UtStreamIterator implements Iterator {
+ int index;
+
+ UtStreamIterator(int index) {
+ if (index < 0 || index > elementData.end) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ this.index = index;
+ }
+
+ @Override
+ public boolean hasNext() {
+ preconditionCheck();
+
+ return index != elementData.end;
+ }
+
+ @Override
+ public E next() {
+ preconditionCheck();
+
+ if (index == elementData.end) {
+ throw new NoSuchElementException();
+ }
+
+ return elementData.get(index++);
+ }
+ }
+}
diff --git a/utbot-framework/src/main/kotlin/org/utbot/analytics/EngineAnalyticsContext.kt b/utbot-framework/src/main/kotlin/org/utbot/analytics/EngineAnalyticsContext.kt
new file mode 100644
index 0000000000..b5624e8874
--- /dev/null
+++ b/utbot-framework/src/main/kotlin/org/utbot/analytics/EngineAnalyticsContext.kt
@@ -0,0 +1,36 @@
+package org.utbot.analytics
+
+import org.utbot.engine.InterProceduralUnitGraph
+import org.utbot.engine.selectors.NNRewardGuidedSelectorFactory
+import org.utbot.engine.selectors.NNRewardGuidedSelectorWithRecalculationFactory
+import org.utbot.engine.selectors.NNRewardGuidedSelectorWithoutRecalculationFactory
+import org.utbot.framework.NNRewardGuidedSelectorType
+import org.utbot.framework.UtSettings
+
+/**
+ * Class that stores all objects that need for work analytics module during symbolic execution
+ */
+object EngineAnalyticsContext {
+ var featureProcessorFactory: FeatureProcessorFactory = object : FeatureProcessorFactory {
+ override fun invoke(graph: InterProceduralUnitGraph): FeatureProcessor {
+ error("Feature processor factory is not provided.")
+ }
+ }
+
+ var featureExtractorFactory: FeatureExtractorFactory = object : FeatureExtractorFactory {
+ override fun invoke(graph: InterProceduralUnitGraph): FeatureExtractor {
+ error("Feature extractor factory is not provided.")
+ }
+ }
+
+ val nnRewardGuidedSelectorFactory: NNRewardGuidedSelectorFactory = when (UtSettings.nnRewardGuidedSelectorType) {
+ NNRewardGuidedSelectorType.WITHOUT_RECALCULATION -> NNRewardGuidedSelectorWithoutRecalculationFactory()
+ NNRewardGuidedSelectorType.WITH_RECALCULATION -> NNRewardGuidedSelectorWithRecalculationFactory()
+ }
+
+ var stateRewardPredictorFactory: StateRewardPredictorFactory = object : StateRewardPredictorFactory {
+ override fun invoke(): StateRewardPredictor {
+ error("NNStateRewardPredictor factory wasn't provided")
+ }
+ }
+}
\ No newline at end of file
diff --git a/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureExtractor.kt b/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureExtractor.kt
new file mode 100644
index 0000000000..c86cad1b54
--- /dev/null
+++ b/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureExtractor.kt
@@ -0,0 +1,14 @@
+package org.utbot.analytics
+
+import org.utbot.engine.ExecutionState
+
+/**
+ * Class that encapsulates work with FeatureExtractor during symbolic execution.
+ */
+interface FeatureExtractor {
+ /**
+ * Extract features and store in it [ExecutionState.features]
+ * @param generatedTestCases number of generated tests so far
+ */
+ fun extractFeatures(executionState: ExecutionState, generatedTestCases: Int)
+}
\ No newline at end of file
diff --git a/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureExtractorFactory.kt b/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureExtractorFactory.kt
new file mode 100644
index 0000000000..6ad7a916a6
--- /dev/null
+++ b/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureExtractorFactory.kt
@@ -0,0 +1,10 @@
+package org.utbot.analytics
+
+import org.utbot.engine.InterProceduralUnitGraph
+
+/**
+ * Class that can create FeatureExtractor. See [FeatureExtractor].
+ */
+interface FeatureExtractorFactory {
+ operator fun invoke(graph: InterProceduralUnitGraph): FeatureExtractor
+}
\ No newline at end of file
diff --git a/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureProcessor.kt b/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureProcessor.kt
new file mode 100644
index 0000000000..e69e783a97
--- /dev/null
+++ b/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureProcessor.kt
@@ -0,0 +1,14 @@
+package org.utbot.analytics
+
+import org.utbot.engine.InterProceduralUnitGraph
+import org.utbot.engine.selectors.strategies.TraverseGraphStatistics
+
+/**
+ * Interface that encapsulates work with FeatureProcessor and can only dumpFeatures at the end of symbolic execution
+ */
+abstract class FeatureProcessor(graph: InterProceduralUnitGraph) : TraverseGraphStatistics(graph) {
+ /**
+ * Dump features and rewards of all states in collected test cases.
+ */
+ abstract fun dumpFeatures()
+}
diff --git a/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureProcessorFactory.kt b/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureProcessorFactory.kt
new file mode 100644
index 0000000000..d012aa7e89
--- /dev/null
+++ b/utbot-framework/src/main/kotlin/org/utbot/analytics/FeatureProcessorFactory.kt
@@ -0,0 +1,10 @@
+package org.utbot.analytics
+
+import org.utbot.engine.InterProceduralUnitGraph
+
+/**
+ * Class that can create FeatureProcessor. See [FeatureProcessor]
+ */
+interface FeatureProcessorFactory {
+ operator fun invoke(graph: InterProceduralUnitGraph): FeatureProcessor
+}
\ No newline at end of file
diff --git a/utbot-framework/src/main/kotlin/org/utbot/analytics/Predictors.kt b/utbot-framework/src/main/kotlin/org/utbot/analytics/Predictors.kt
index d7876049cb..562d6db7c3 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/analytics/Predictors.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/analytics/Predictors.kt
@@ -1,7 +1,6 @@
package org.utbot.analytics
import org.utbot.engine.pc.UtExpression
-import kotlinx.collections.immutable.PersistentList
import soot.jimple.Stmt
/**
@@ -18,9 +17,16 @@ object Predictors {
* Predict z3's [Solver.check()] execution time in nanoseconds
*/
var smt: UtBotNanoTimePredictor> = object : UtBotNanoTimePredictor> {}
- var smtIncremental: UtBotNanoTimePredictor = object : UtBotNanoTimePredictor {}
+ var smtIncremental: UtBotNanoTimePredictor = object : UtBotNanoTimePredictor {}
var testName: UtBotAbstractPredictor, String> =
object : UtBotAbstractPredictor, String> {
override fun predict(input: Iterable): String = "stubName"
}
+
+ var stateRewardPredictor: UtBotAbstractPredictor, Double> =
+ object : UtBotAbstractPredictor, Double> {
+ override fun predict(input: List): Double {
+ error("stateRewardPredictor is not provided.")
+ }
+ }
}
\ No newline at end of file
diff --git a/utbot-framework/src/main/kotlin/org/utbot/analytics/StateRewardPredictor.kt b/utbot-framework/src/main/kotlin/org/utbot/analytics/StateRewardPredictor.kt
new file mode 100644
index 0000000000..bcb55a7eeb
--- /dev/null
+++ b/utbot-framework/src/main/kotlin/org/utbot/analytics/StateRewardPredictor.kt
@@ -0,0 +1,6 @@
+package org.utbot.analytics
+
+/**
+ * Interface, which should predict reward for state by features list.
+ */
+interface StateRewardPredictor : UtBotAbstractPredictor, Double>
\ No newline at end of file
diff --git a/utbot-framework/src/main/kotlin/org/utbot/analytics/StateRewardPredictorFactory.kt b/utbot-framework/src/main/kotlin/org/utbot/analytics/StateRewardPredictorFactory.kt
new file mode 100644
index 0000000000..60d1aa9b40
--- /dev/null
+++ b/utbot-framework/src/main/kotlin/org/utbot/analytics/StateRewardPredictorFactory.kt
@@ -0,0 +1,8 @@
+package org.utbot.analytics
+
+/**
+ * Encapsulates creation of [StateRewardPredictor]
+ */
+interface StateRewardPredictorFactory {
+ operator fun invoke(): StateRewardPredictor
+}
\ No newline at end of file
diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/AnnotationResolver.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/AnnotationResolver.kt
index 31033a9eec..e6509898d6 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/engine/AnnotationResolver.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/engine/AnnotationResolver.kt
@@ -109,12 +109,6 @@ val SootMethod.findMockAnnotationOrNull
val SootMethod.hasInternalMockAnnotation
get() = annotationsOrNull?.singleOrNull { it.type == utInternalUsageBytecodeSignature } != null
-/**
- * Returns true if the [SootMethod]'s signature is equal to [UtMock.assume]'s signature, false otherwise.
- */
-val SootMethod.isUtMockAssume
- get() = signature == assumeMethod.signature
-
val utClassMockBytecodeSignature = UtClassMock::class.java.bytecodeSignature()
val utConstructorMockBytecodeSignature = UtConstructorMock::class.java.bytecodeSignature()
val utInternalUsageBytecodeSignature = UtInternalUsage::class.java.bytecodeSignature()
diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt
index 41db4cbefa..5c53d0c751 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt
@@ -26,18 +26,17 @@ import org.utbot.framework.plugin.api.UtNullModel
import org.utbot.framework.plugin.api.UtPrimitiveModel
import org.utbot.framework.plugin.api.UtReferenceModel
import org.utbot.framework.plugin.api.util.id
+import org.utbot.framework.plugin.api.util.objectArrayClassId
import org.utbot.framework.plugin.api.util.objectClassId
+import soot.ArrayType
import soot.Scene
+import soot.SootClass
+import soot.SootField
import soot.SootMethod
val rangeModifiableArrayId: ClassId = RangeModifiableUnlimitedArray::class.id
class RangeModifiableUnlimitedArrayWrapper : WrapperInterface {
- private val rangeModifiableArrayClass = Scene.v().getSootClass(rangeModifiableArrayId.name)
- private val beginField = rangeModifiableArrayClass.getField("int begin")
- private val endField = rangeModifiableArrayClass.getField("int end")
- private val storageField = rangeModifiableArrayClass.getField("java.lang.Object[] storage")
-
override fun UtBotSymbolicEngine.invoke(
wrapper: ObjectValue,
method: SootMethod,
@@ -168,13 +167,15 @@ class RangeModifiableUnlimitedArrayWrapper : WrapperInterface {
val typeStorage = typeResolver.constructTypeStorage(OBJECT_TYPE.arrayType, useConcreteType = false)
val array = ArrayValue(typeStorage, arrayAddr)
+ val hardConstraints = setOf(
+ Eq(memory.findArrayLength(arrayAddr), length),
+ typeRegistry.typeConstraint(arrayAddr, array.typeStorage).all(),
+ ).asHardConstraint()
+
listOf(
MethodResult(
SymbolicSuccess(array),
- hardConstraints = setOf(
- Eq(memory.findArrayLength(arrayAddr), length),
- typeRegistry.typeConstraint(array.addr, array.typeStorage).all()
- ).asHardConstraint(),
+ hardConstraints = hardConstraints,
memoryUpdates = arrayUpdateWithValue(arrayAddr, OBJECT_TYPE.arrayType, value)
)
)
@@ -233,7 +234,7 @@ class RangeModifiableUnlimitedArrayWrapper : WrapperInterface {
val resultModel = UtArrayModel(
concreteAddr,
- objectClassId,
+ objectArrayClassId,
sizeValue,
UtNullModel(objectClassId),
mutableMapOf()
@@ -243,17 +244,35 @@ class RangeModifiableUnlimitedArrayWrapper : WrapperInterface {
// the constructed model to avoid infinite recursion below
resolver.addConstructedModel(concreteAddr, resultModel)
+ // try to retrieve type storage for the single type parameter
+ val typeStorage =
+ resolver.typeRegistry.getTypeStoragesForObjectTypeParameters(wrapper.addr)?.singleOrNull() ?: TypeRegistry.objectTypeStorage
+
(0 until sizeValue).associateWithTo(resultModel.stores) { i ->
- resolver.resolveModel(
- ObjectValue(
- TypeStorage(OBJECT_TYPE),
- UtAddrExpression(arrayExpression.select(mkInt(i + firstValue)))
- )
- )
+ val addr = UtAddrExpression(arrayExpression.select(mkInt(i + firstValue)))
+
+ val value = if (typeStorage.leastCommonType is ArrayType) {
+ ArrayValue(typeStorage, addr)
+ } else {
+ ObjectValue(typeStorage, addr)
+ }
+
+ resolver.resolveModel(value)
}
return resultModel
}
+
+ companion object {
+ internal val rangeModifiableArrayClass: SootClass
+ get() = Scene.v().getSootClass(rangeModifiableArrayId.name)
+ internal val beginField: SootField
+ get() = rangeModifiableArrayClass.getFieldByName("begin")
+ internal val endField: SootField
+ get() = rangeModifiableArrayClass.getFieldByName("end")
+ internal val storageField: SootField
+ get() = rangeModifiableArrayClass.getFieldByName("storage")
+ }
}
val associativeArrayId: ClassId = AssociativeArray::class.id
diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt
index 3b74f25a60..55a65470cf 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt
@@ -10,6 +10,7 @@ import org.utbot.engine.overrides.collections.UtHashSet
import org.utbot.engine.overrides.collections.UtLinkedList
import org.utbot.engine.pc.UtAddrExpression
import org.utbot.engine.pc.UtExpression
+import org.utbot.engine.pc.UtFalse
import org.utbot.engine.pc.select
import org.utbot.engine.symbolic.asHardConstraint
import org.utbot.engine.z3.intValue
@@ -33,7 +34,6 @@ import org.utbot.framework.plugin.api.util.id
import org.utbot.framework.plugin.api.util.methodId
import org.utbot.framework.plugin.api.util.objectClassId
import org.utbot.framework.util.nextModelName
-import java.util.LinkedList
import soot.IntType
import soot.RefType
import soot.Scene
@@ -74,7 +74,6 @@ abstract class BaseOverriddenWrapper(protected val overriddenClassName: String)
method: SootMethod,
parameters: List
): List {
-
val methodResults = overrideInvoke(wrapper, method, parameters)
if (methodResults != null) {
return methodResults
@@ -84,35 +83,57 @@ abstract class BaseOverriddenWrapper(protected val overriddenClassName: String)
return listOf(GraphResult(method.jimpleBody().graph()))
}
- val overriddenMethod = overriddenClass.findMethodOrNull(method.subSignature)
-
- val jimpleBody = overriddenMethod?.jimpleBody() ?: method.jimpleBody()
- val graphResult = GraphResult(jimpleBody.graph())
-
- return listOf(graphResult)
+ // We need to find either an override from the class (for example, implementation
+ // of the method from the wrapper) or a method from its ancestors.
+ // Note that the method from the ancestor might have substitutions as well.
+ // I.e., it is `toString` method for `UtArrayList` that is defined in
+ // `AbstractCollection` and has its own overridden implementation.
+ val overriddenMethod = overriddenClass
+ .findMethodOrNull(method.subSignature)
+ ?.let { typeRegistry.findSubstitutionOrNull(it) ?: it }
+
+ return if (overriddenMethod == null) {
+ // No overridden method has been found, switch to concrete execution
+ pathLogger.warn("Method ${overriddenClass.name}::${method.subSignature} not found, executing concretely")
+ emptyList()
+ } else {
+ val jimpleBody = overriddenMethod.jimpleBody()
+ val graphResult = GraphResult(jimpleBody.graph())
+ listOf(graphResult)
+ }
}
}
/**
- * WrapperInterface that proxies an implementation with methods of [overriddenClass].
+ * Wrapper for a particular [java.util.Collection] or [java.util.Map] or [java.util.stream.Stream].
*/
-abstract class BaseCollectionWrapper(collectionClassName: String) : BaseOverriddenWrapper(collectionClassName) {
+abstract class BaseContainerWrapper(containerClassName: String) : BaseOverriddenWrapper(containerClassName) {
/**
* Resolve [wrapper] to [UtAssembleModel] using [resolver].
*/
override fun value(resolver: Resolver, wrapper: ObjectValue): UtAssembleModel = resolver.run {
- val classId = chooseClassIdWithConstructor(wrapper.type.sootClass.id)
val addr = holder.concreteAddr(wrapper.addr)
val modelName = nextModelName(baseModelName)
val parameterModels = resolveValueModels(wrapper)
+ val classId = chooseClassIdWithConstructor(wrapper.type.sootClass.id)
+
val instantiationChain = mutableListOf()
val modificationsChain = mutableListOf()
- return UtAssembleModel(addr, classId, modelName, instantiationChain, modificationsChain)
+
+ UtAssembleModel(addr, classId, modelName, instantiationChain, modificationsChain)
.apply {
- instantiationChain += UtExecutableCallModel(null, constructorId(classId), emptyList(), this)
- modificationsChain += parameterModels.map { UtExecutableCallModel(this, modificationMethodId, it) }
+ instantiationChain += UtExecutableCallModel(
+ instance = null,
+ executable = constructorId(classId),
+ params = emptyList(),
+ returnValue = this
+ )
+
+ modificationsChain += parameterModels.map {
+ UtExecutableCallModel(this, modificationMethodId, it)
+ }
}
}
@@ -140,6 +161,36 @@ abstract class BaseCollectionWrapper(collectionClassName: String) : BaseOverridd
override fun toString() = "$overriddenClassName()"
}
+abstract class BaseGenericStorageBasedContainerWrapper(containerClassName: String) : BaseContainerWrapper(containerClassName) {
+ override fun UtBotSymbolicEngine.overrideInvoke(
+ wrapper: ObjectValue,
+ method: SootMethod,
+ parameters: List
+ ): List? =
+ when (method.signature) {
+ UT_GENERIC_STORAGE_SET_EQUAL_GENERIC_TYPE_SIGNATURE -> {
+ val equalGenericTypeConstraint = typeRegistry
+ .eqGenericSingleTypeParameterConstraint(parameters[0].addr, wrapper.addr)
+ .asHardConstraint()
+
+ val methodResult = MethodResult(
+ SymbolicSuccess(voidValue),
+ equalGenericTypeConstraint
+ )
+
+ listOf(methodResult)
+ }
+ else -> null
+ }
+
+ override fun Resolver.resolveValueModels(wrapper: ObjectValue): List> {
+ val elementDataFieldId = FieldId(overriddenClass.type.classId, "elementData")
+ val arrayModel = collectFieldModels(wrapper.addr, overriddenClass.type)[elementDataFieldId] as? UtArrayModel
+
+ return arrayModel?.let { constructValues(arrayModel, arrayModel.length) } ?: emptyList()
+ }
+}
+
/**
* Auxiliary enum class for specifying an implementation for [ListWrapper], that it will use.
*/
@@ -165,30 +216,7 @@ enum class UtListClass {
* Modification chain consists of consequent [java.util.List.add] methods
* that are arranged to iterating order of list.
*/
-class ListWrapper(private val utListClass: UtListClass) : BaseCollectionWrapper(utListClass.className) {
- override fun UtBotSymbolicEngine.overrideInvoke(
- wrapper: ObjectValue,
- method: SootMethod,
- parameters: List
- ): List? =
- if (method.signature == UT_GENERIC_STORAGE_SET_EQUAL_GENERIC_TYPE_SIGNATURE) {
- listOf(
- MethodResult(
- SymbolicSuccess(voidValue),
- typeRegistry.eqGenericSingleTypeParameterConstraint(parameters[0].addr, wrapper.addr).asHardConstraint()
- )
- )
- } else {
- null
- }
-
- override fun Resolver.resolveValueModels(wrapper: ObjectValue): List> {
- val elementDataFieldId = FieldId(overriddenClass.type.classId, "elementData")
- val arrayModel = collectFieldModels(wrapper.addr, overriddenClass.type)[elementDataFieldId] as? UtArrayModel
-
- return arrayModel?.let { constructValues(arrayModel, arrayModel.length) } ?: emptyList()
- }
-
+class ListWrapper(private val utListClass: UtListClass) : BaseGenericStorageBasedContainerWrapper(utListClass.className) {
/**
* Chooses proper class for instantiation. Uses [java.util.ArrayList] instead of [java.util.List]
* or [java.util.AbstractList].
@@ -203,7 +231,7 @@ class ListWrapper(private val utListClass: UtListClass) : BaseCollectionWrapper(
classId = java.util.List::class.id,
name = "add",
returnType = booleanClassId,
- arguments = arrayOf(java.lang.Object::class.id),
+ arguments = arrayOf(objectClassId),
)
override val baseModelName = "list"
@@ -221,31 +249,7 @@ class ListWrapper(private val utListClass: UtListClass) : BaseCollectionWrapper(
* through [java.util.HashSet] in program and generated test depends on the order of
* entries, then real behavior of generated test can differ from expected and undefined.
*/
-class SetWrapper : BaseCollectionWrapper(UtHashSet::class.qualifiedName!!) {
- override fun UtBotSymbolicEngine.overrideInvoke(
- wrapper: ObjectValue,
- method: SootMethod,
- parameters: List
- ): List? =
- if (method.signature == UT_GENERIC_STORAGE_SET_EQUAL_GENERIC_TYPE_SIGNATURE) {
- listOf(
- MethodResult(
- SymbolicSuccess(voidValue),
- typeRegistry.eqGenericSingleTypeParameterConstraint(parameters[0].addr, wrapper.addr)
- .asHardConstraint()
- )
- )
- } else {
- null
- }
-
- override fun Resolver.resolveValueModels(wrapper: ObjectValue): List> {
- val elementDataFieldId = FieldId(overriddenClass.type.classId, "elementData")
- val arrayModel = collectFieldModels(wrapper.addr, overriddenClass.type)[elementDataFieldId] as? UtArrayModel
-
- return arrayModel?.let { constructValues(arrayModel, arrayModel.length) } ?: emptyList()
- }
-
+class SetWrapper : BaseGenericStorageBasedContainerWrapper(UtHashSet::class.qualifiedName!!) {
/**
* Chooses proper class for instantiation. Uses [java.util.ArrayList] instead of [java.util.List]
* or [java.util.AbstractList].
@@ -260,7 +264,7 @@ class SetWrapper : BaseCollectionWrapper(UtHashSet::class.qualifiedName!!) {
classId = java.util.Set::class.id,
name = "add",
returnType = booleanClassId,
- arguments = arrayOf(java.lang.Object::class.id),
+ arguments = arrayOf(objectClassId),
)
override val baseModelName: String = "set"
@@ -278,32 +282,32 @@ class SetWrapper : BaseCollectionWrapper(UtHashSet::class.qualifiedName!!) {
* through [java.util.HashMap] in program and generated test depends on the order of
* entries, then real behavior of generated test can differ from expected and undefined.
*/
-class MapWrapper : BaseCollectionWrapper(UtHashMap::class.qualifiedName!!) {
+class MapWrapper : BaseContainerWrapper(UtHashMap::class.qualifiedName!!) {
override fun UtBotSymbolicEngine.overrideInvoke(
wrapper: ObjectValue,
method: SootMethod,
parameters: List
- ): List? {
- return when (method.signature) {
+ ): List? =
+ when (method.signature) {
UT_GENERIC_STORAGE_SET_EQUAL_GENERIC_TYPE_SIGNATURE -> listOf(
MethodResult(
SymbolicSuccess(voidValue),
- typeRegistry.eqGenericSingleTypeParameterConstraint(parameters[0].addr, wrapper.addr).asHardConstraint()
+ typeRegistry.eqGenericSingleTypeParameterConstraint(parameters[0].addr, wrapper.addr)
+ .asHardConstraint()
)
)
UT_GENERIC_ASSOCIATIVE_SET_EQUAL_GENERIC_TYPE_SIGNATURE -> listOf(
MethodResult(
SymbolicSuccess(voidValue),
- typeRegistry.eqGenericTypeParametersConstraint(
- parameters[0].addr,
- wrapper.addr,
- parameterSize = 2
- ).asHardConstraint()
+ typeRegistry.eqGenericTypeParametersConstraint(
+ parameters[0].addr,
+ wrapper.addr,
+ parameterSize = 2
+ ).asHardConstraint()
)
)
else -> null
}
- }
override fun Resolver.resolveValueModels(wrapper: ObjectValue): List> {
val fieldModels = collectFieldModels(wrapper.addr, overriddenClass.type)
@@ -344,7 +348,7 @@ class MapWrapper : BaseCollectionWrapper(UtHashMap::class.qualifiedName!!) {
/**
* Constructs collection values using underlying array model. If model is null model, returns list of nulls.
*/
-private fun constructValues(model: UtModel, size: Int): List> = when (model) {
+internal fun constructValues(model: UtModel, size: Int): List> = when (model) {
is UtArrayModel -> List(size) { listOf(model.stores[it] ?: model.constModel) }
is UtNullModel -> {
val elementClassId = model.classId.elementClassId
@@ -387,7 +391,7 @@ private fun constructKeysAndValues(keysModel: UtModel, valuesModel: UtModel, siz
private val UT_GENERIC_STORAGE_CLASS
get() = Scene.v().getSootClass(UtGenericStorage::class.java.canonicalName)
-private val UT_GENERIC_STORAGE_SET_EQUAL_GENERIC_TYPE_SIGNATURE =
+internal val UT_GENERIC_STORAGE_SET_EQUAL_GENERIC_TYPE_SIGNATURE =
UT_GENERIC_STORAGE_CLASS.getMethodByName(UtGenericStorage<*>::setEqualGenericType.name).signature
private val UT_GENERIC_ASSOCIATIVE_CLASS
@@ -397,9 +401,9 @@ private val UT_GENERIC_ASSOCIATIVE_SET_EQUAL_GENERIC_TYPE_SIGNATURE =
UT_GENERIC_ASSOCIATIVE_CLASS.getMethodByName(UtGenericAssociative<*, *>::setEqualGenericType.name).signature
val ARRAY_LIST_TYPE: RefType
- get() = Scene.v().getSootClass(ArrayList::class.java.canonicalName).type
+ get() = Scene.v().getSootClass(java.util.ArrayList::class.java.canonicalName).type
val LINKED_LIST_TYPE: RefType
- get() = Scene.v().getSootClass(LinkedList::class.java.canonicalName).type
+ get() = Scene.v().getSootClass(java.util.LinkedList::class.java.canonicalName).type
val LINKED_HASH_SET_TYPE: RefType
get() = Scene.v().getSootClass(java.util.LinkedHashSet::class.java.canonicalName).type
@@ -411,6 +415,9 @@ val LINKED_HASH_MAP_TYPE: RefType
val HASH_MAP_TYPE: RefType
get() = Scene.v().getSootClass(java.util.HashMap::class.java.canonicalName).type
+val STREAM_TYPE: RefType
+ get() = Scene.v().getSootClass(java.util.stream.Stream::class.java.canonicalName).type
+
internal fun UtBotSymbolicEngine.getArrayField(
addr: UtAddrExpression,
wrapperClass: SootClass,
diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/DataClasses.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/DataClasses.kt
index 1d0347fb82..860d1c7d71 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/engine/DataClasses.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/engine/DataClasses.kt
@@ -8,6 +8,7 @@ import org.utbot.engine.pc.UtIsExpression
import org.utbot.engine.pc.UtTrue
import org.utbot.engine.pc.mkAnd
import org.utbot.engine.pc.mkOr
+import org.utbot.engine.symbolic.Assumption
import org.utbot.engine.symbolic.HardConstraint
import org.utbot.engine.symbolic.SoftConstraint
import org.utbot.engine.symbolic.SymbolicStateUpdate
@@ -134,15 +135,17 @@ data class MethodResult(
symbolicResult: SymbolicResult,
hardConstraints: HardConstraint = HardConstraint(),
softConstraints: SoftConstraint = SoftConstraint(),
+ assumption: Assumption = Assumption(),
memoryUpdates: MemoryUpdate = MemoryUpdate()
- ) : this(symbolicResult, SymbolicStateUpdate(hardConstraints, softConstraints, memoryUpdates))
+ ) : this(symbolicResult, SymbolicStateUpdate(hardConstraints, softConstraints, assumption, memoryUpdates))
constructor(
value: SymbolicValue,
hardConstraints: HardConstraint = HardConstraint(),
softConstraints: SoftConstraint = SoftConstraint(),
+ assumption: Assumption = Assumption(),
memoryUpdates: MemoryUpdate = MemoryUpdate(),
- ) : this(SymbolicSuccess(value), hardConstraints, softConstraints, memoryUpdates)
+ ) : this(SymbolicSuccess(value), hardConstraints, softConstraints, assumption, memoryUpdates)
}
/**
diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/ExecutionState.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/ExecutionState.kt
index 79ab953a89..9c831771c0 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/engine/ExecutionState.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/engine/ExecutionState.kt
@@ -1,10 +1,5 @@
package org.utbot.engine
-import org.utbot.common.md5
-import org.utbot.engine.pc.UtSolver
-import org.utbot.engine.symbolic.SymbolicState
-import org.utbot.engine.symbolic.SymbolicStateUpdate
-import org.utbot.framework.plugin.api.Step
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.PersistentSet
@@ -12,9 +7,16 @@ import kotlinx.collections.immutable.persistentHashMapOf
import kotlinx.collections.immutable.persistentHashSetOf
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.plus
+import org.utbot.common.md5
+import org.utbot.engine.pc.UtSolver
import org.utbot.engine.pc.UtSolverStatusUNDEFINED
+import org.utbot.engine.symbolic.SymbolicState
+import org.utbot.engine.symbolic.SymbolicStateUpdate
+import org.utbot.framework.UtSettings
+import org.utbot.framework.plugin.api.Step
import soot.SootMethod
import soot.jimple.Stmt
+import java.util.Objects
const val RETURN_DECISION_NUM = -1
const val CALL_DECISION_NUM = -2
@@ -40,6 +42,55 @@ data class ExecutionStackElement(
this.copy(localVariableMemory = localVariableMemory.update(memoryUpdate), doesntThrow = doesntThrow)
}
+/**
+ * Class that store all information about execution state that needed only for analytics module
+ */
+data class StateAnalyticsProperties(
+ /**
+ * Number of forks already performed along state's path, where fork is statement with multiple successors
+ */
+ val depth: Int = 0,
+ var visitedAfterLastFork: Int = 0,
+ var visitedBeforeLastFork: Int = 0,
+ var stmtsSinceLastCovered: Int = 0,
+ val parent: ExecutionState? = null,
+) {
+ var executingTime: Long = 0
+ var reward: Double? = null
+ val features: MutableList = mutableListOf()
+
+ /**
+ * Flag that indicates whether this state is fork or not. Fork here means that we have more than one successor
+ */
+ private var isFork: Boolean = false
+
+ fun definitelyFork() {
+ isFork = true
+ }
+
+ private var isVisitedNew: Boolean = false
+
+ fun updateIsVisitedNew() {
+ isVisitedNew = true
+ stmtsSinceLastCovered = 0
+ visitedAfterLastFork++
+ }
+
+ private val successorDepth: Int get() = depth + if (isFork) 1 else 0
+
+ private val successorVisitedAfterLastFork: Int get() = if (!isFork) visitedAfterLastFork else 0
+ private val successorVisitedBeforeLastFork: Int get() = visitedBeforeLastFork + if (isFork) visitedAfterLastFork else 0
+ private val successorStmtSinceLastCovered: Int get() = 1 + stmtsSinceLastCovered
+
+ fun successorProperties(parent: ExecutionState) = StateAnalyticsProperties(
+ successorDepth,
+ successorVisitedAfterLastFork,
+ successorVisitedBeforeLastFork,
+ successorStmtSinceLastCovered,
+ if (UtSettings.enableFeatureProcess) parent else null
+ )
+}
+
/**
* [visitedStatementsHashesToCountInPath] is a map representing how many times each instruction from the [path]
* has occurred. It is required to calculate priority of the branches and decrease the priority for branches leading
@@ -61,12 +112,14 @@ data class ExecutionState(
val lastMethod: SootMethod? = null,
val methodResult: MethodResult? = null,
val exception: SymbolicFailure? = null,
- private var outgoingEdges: Int = 0
+ private var stateAnalyticsProperties: StateAnalyticsProperties = StateAnalyticsProperties()
) : AutoCloseable {
val solver: UtSolver by symbolicState::solver
val memory: Memory by symbolicState::memory
+ private var outgoingEdges = 0
+
fun isInNestedMethod() = executionStack.size > 1
val localVariableMemory
@@ -107,7 +160,8 @@ data class ExecutionState(
pathLength = pathLength + 1,
lastEdge = edge,
lastMethod = executionStack.last().method,
- exception = exception
+ exception = exception,
+ stateAnalyticsProperties = stateAnalyticsProperties.successorProperties(this)
)
}
@@ -123,14 +177,18 @@ data class ExecutionState(
symbolicState = symbolicState,
executionStack = executionStack.removeAt(executionStack.lastIndex),
path = path + stmt,
- visitedStatementsHashesToCountInPath = visitedStatementsHashesToCountInPath.put(stmtHashcode, stmtCountInPath),
+ visitedStatementsHashesToCountInPath = visitedStatementsHashesToCountInPath.put(
+ stmtHashcode,
+ stmtCountInPath
+ ),
decisionPath = decisionPath + edge.decisionNum,
edges = edges + edge,
stmts = stmts.putIfAbsent(stmt, pathLength),
pathLength = pathLength + 1,
lastEdge = edge,
lastMethod = executionStack.last().method,
- methodResult
+ methodResult,
+ stateAnalyticsProperties = stateAnalyticsProperties.successorProperties(this)
)
}
@@ -158,13 +216,17 @@ data class ExecutionState(
symbolicState = symbolicState.stateForNestedMethod() + update,
executionStack = executionStack + stackElement,
path = path + this.stmt,
- visitedStatementsHashesToCountInPath = visitedStatementsHashesToCountInPath.put(stmtHashCode, stmtCountInPath),
+ visitedStatementsHashesToCountInPath = visitedStatementsHashesToCountInPath.put(
+ stmtHashCode,
+ stmtCountInPath
+ ),
decisionPath = decisionPath + edge.decisionNum,
edges = edges + edge,
stmts = stmts.putIfAbsent(this.stmt, pathLength),
pathLength = pathLength + 1,
lastEdge = edge,
- lastMethod = stackElement.method
+ lastMethod = stackElement.method,
+ stateAnalyticsProperties = stateAnalyticsProperties.successorProperties(this)
)
}
@@ -173,7 +235,10 @@ data class ExecutionState(
): ExecutionState {
val last = executionStack.last()
val stackElement = last.update(stateUpdate.localMemoryUpdates)
- return copy(symbolicState = symbolicState + stateUpdate, executionStack = executionStack.set(executionStack.lastIndex, stackElement))
+ return copy(
+ symbolicState = symbolicState + stateUpdate,
+ executionStack = executionStack.set(executionStack.lastIndex, stackElement)
+ )
}
fun update(
@@ -196,13 +261,17 @@ data class ExecutionState(
symbolicState = symbolicState + symbolicStateUpdate,
executionStack = executionStack.set(executionStack.lastIndex, stackElement),
path = path + stmt,
- visitedStatementsHashesToCountInPath = visitedStatementsHashesToCountInPath.put(stmtHashCode, stmtCountInPath),
+ visitedStatementsHashesToCountInPath = visitedStatementsHashesToCountInPath.put(
+ stmtHashCode,
+ stmtCountInPath
+ ),
decisionPath = decisionPath + edge.decisionNum,
edges = edges + edge,
stmts = stmts.putIfAbsent(stmt, pathLength),
pathLength = pathLength + 1,
lastEdge = edge,
- lastMethod = stackElement.method
+ lastMethod = stackElement.method,
+ stateAnalyticsProperties = stateAnalyticsProperties.successorProperties(this)
)
}
@@ -251,14 +320,70 @@ data class ExecutionState(
*/
fun prettifiedPathLog(): String {
val path = fullPath()
- val prettifiedPath = path.joinToString(separator = "\n") { (stmt, depth, decision) ->
+ val prettifiedPath = prettifiedPath(path)
+ return " MD5(path)=${md5(prettifiedPath)}\n$prettifiedPath"
+ }
+
+ private fun md5(prettifiedPath: String) = prettifiedPath.md5()
+
+ fun md5() = prettifiedPath(fullPath()).md5()
+
+ private fun prettifiedPath(path: List) =
+ path.joinToString(separator = "\n") { (stmt, depth, decision) ->
val prefix = when (decision) {
- CALL_DECISION_NUM -> "call[${depth}] - " + "".padEnd(2*depth, ' ')
- RETURN_DECISION_NUM -> " ret[${depth - 1}] - " + "".padEnd(2*depth, ' ')
- else -> " "+"".padEnd(2*depth, ' ')
+ CALL_DECISION_NUM -> "call[${depth}] - " + "".padEnd(2 * depth, ' ')
+ RETURN_DECISION_NUM -> " ret[${depth - 1}] - " + "".padEnd(2 * depth, ' ')
+ else -> " " + "".padEnd(2 * depth, ' ')
}
"$prefix$stmt"
}
- return " MD5(path)=${prettifiedPath.md5()}\n$prettifiedPath"
+
+ fun definitelyFork() {
+ stateAnalyticsProperties.definitelyFork()
}
+
+ fun updateIsVisitedNew() {
+ stateAnalyticsProperties.updateIsVisitedNew()
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as ExecutionState
+
+ if (stmt != other.stmt) return false
+ if (symbolicState != other.symbolicState) return false
+ if (executionStack != other.executionStack) return false
+ if (path != other.path) return false
+ if (visitedStatementsHashesToCountInPath != other.visitedStatementsHashesToCountInPath) return false
+ if (decisionPath != other.decisionPath) return false
+ if (edges != other.edges) return false
+ if (stmts != other.stmts) return false
+ if (pathLength != other.pathLength) return false
+ if (lastEdge != other.lastEdge) return false
+ if (lastMethod != other.lastMethod) return false
+ if (methodResult != other.methodResult) return false
+ if (exception != other.exception) return false
+
+ return true
+ }
+
+ private val hashCode by lazy {
+ Objects.hash(
+ stmt, symbolicState, executionStack, path, visitedStatementsHashesToCountInPath, decisionPath,
+ edges, stmts, pathLength, lastEdge, lastMethod, methodResult, exception
+ )
+ }
+
+ override fun hashCode(): Int = hashCode
+
+ var reward by stateAnalyticsProperties::reward
+ val features by stateAnalyticsProperties::features
+ var executingTime by stateAnalyticsProperties::executingTime
+ val depth by stateAnalyticsProperties::depth
+ var visitedBeforeLastFork by stateAnalyticsProperties::visitedBeforeLastFork
+ var visitedAfterLastFork by stateAnalyticsProperties::visitedAfterLastFork
+ var stmtsSinceLastCovered by stateAnalyticsProperties::stmtsSinceLastCovered
+ val parent by stateAnalyticsProperties::parent
}
\ No newline at end of file
diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt
index 0010195e18..d94d51b1b6 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt
@@ -30,7 +30,6 @@ import org.utbot.engine.pc.mkLong
import org.utbot.engine.pc.mkShort
import org.utbot.engine.pc.mkString
import org.utbot.engine.pc.toSort
-import org.utbot.framework.UtSettings.checkNpeForFinalFields
import org.utbot.framework.UtSettings.checkNpeInNestedMethods
import org.utbot.framework.UtSettings.checkNpeInNestedNotPrivateMethods
import org.utbot.framework.plugin.api.FieldId
@@ -46,6 +45,7 @@ import kotlin.reflect.jvm.javaConstructor
import kotlin.reflect.jvm.javaMethod
import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentHashMapOf
+import org.utbot.engine.pc.UtSolverStatusUNDEFINED
import soot.ArrayType
import soot.PrimType
import soot.RefLikeType
@@ -382,11 +382,7 @@ fun arrayTypeUpdate(addr: UtAddrExpression, type: ArrayType) =
fun SootField.shouldBeNotNull(): Boolean {
require(type is RefLikeType)
- if (hasNotNullAnnotation()) return true
-
- if (!checkNpeForFinalFields && isFinal) return true
-
- return false
+ return hasNotNullAnnotation()
}
/**
@@ -429,21 +425,33 @@ val SootClass.isUtMock: Boolean
val SootClass.isOverridden: Boolean
get() = packageName.startsWith(UTBOT_OVERRIDE_PACKAGE_NAME)
+val SootClass.isLibraryNonOverriddenClass: Boolean
+ get() = isLibraryClass && !isOverridden
+
/**
* Returns a state from the list that has [UtSolverStatusSAT] status.
* Inside it calls UtSolver.check if required.
+ *
+ * [processStatesWithUnknownStatus] is responsible for solver checks for states
+ * with unknown status. Note that this calculation might take a long time.
*/
-fun MutableList.pollUntilSat(): ExecutionState? {
+fun MutableList.pollUntilSat(processStatesWithUnknownStatus: Boolean): ExecutionState? {
while (!isEmpty()) {
val state = removeLast()
with(state.solver) {
+ if (lastStatus.statusKind == UtSolverStatusKind.UNSAT) return@with
+
if (lastStatus.statusKind == UtSolverStatusKind.SAT) return state
- if (lastStatus.statusKind == UtSolverStatusKind.UNKNOWN) {
- val result = check(respectSoft = true)
+ require(failedAssumptions.isEmpty()) { "There are failed requirements in the queue to execute concretely" }
+
+ if (processStatesWithUnknownStatus) {
+ if (lastStatus == UtSolverStatusUNDEFINED) {
+ val result = check(respectSoft = true)
- if (result.statusKind == UtSolverStatusKind.SAT) return state
+ if (result.statusKind == UtSolverStatusKind.SAT) return state
+ }
}
}
}
@@ -455,3 +463,23 @@ fun isOverriddenClass(type: RefType) = type.sootClass.isOverridden
val SootMethod.isSynthetic: Boolean
get() = soot.Modifier.isSynthetic(modifiers)
+
+/**
+ * Returns true if the [SootMethod]'s signature is equal to [UtMock.assume]'s signature, false otherwise.
+ */
+val SootMethod.isUtMockAssume
+ get() = signature == assumeMethod.signature
+
+/**
+ * Returns true if the [SootMethod]'s signature is equal to
+ * [UtMock.assumeOrExecuteConcretely]'s signature, false otherwise.
+ */
+val SootMethod.isUtMockAssumeOrExecuteConcretely
+ get() = signature == assumeOrExecuteConcretelyMethod.signature
+
+/**
+ * Returns true is the [SootMethod] is defined in a class from
+ * [UTBOT_OVERRIDE_PACKAGE_NAME] package and its name is `preconditionCheck`.
+ */
+val SootMethod.isPreconditionCheckMethod
+ get() = declaringClass.isOverridden && name == "preconditionCheck"
diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/InterProceduralUnitGraph.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/InterProceduralUnitGraph.kt
index 7485abe927..ff533b1085 100644
--- a/utbot-framework/src/main/kotlin/org/utbot/engine/InterProceduralUnitGraph.kt
+++ b/utbot-framework/src/main/kotlin/org/utbot/engine/InterProceduralUnitGraph.kt
@@ -7,6 +7,7 @@ import soot.jimple.Stmt
import soot.jimple.SwitchStmt
import soot.jimple.internal.JReturnStmt
import soot.jimple.internal.JReturnVoidStmt
+import soot.jimple.internal.JThrowStmt
import soot.toolkits.graph.ExceptionalUnitGraph
private const val EXCEPTION_DECISION_SHIFT = 100000
@@ -22,14 +23,28 @@ class InterProceduralUnitGraph(graph: ExceptionalUnitGraph) {
private var attachAllowed = true
val graphs = mutableListOf(graph)
private val statistics = mutableListOf()
- private val methods = mutableListOf(graph.body.method)
+ // All the methods in the InterProceduralUnitGraph
+ private val methods: MutableSet = mutableSetOf(graph.body.method)
+ // Methods with registered edges
+ private val registeredMethods: MutableSet = mutableSetOf(graph.body.method)
+
+ // We use this field for exceptional statements of the methods from the [registeredMethods] map.
+ // Points of interest are statements of the graph that must be covered during the exploration.
+ // Therefore, there is no need to put here statements from registered methods since
+ // we try to cover all of their edges.
+ private val methodToUncoveredThrowStatements: MutableMap> = mutableMapOf()
private val unexceptionalSuccsCache = mutableMapOf>>()
private val exceptionalSuccsCache = mutableMapOf>>()
private val edgesCache = mutableMapOf>()
val stmts: MutableSet = graph.stmts.toMutableSet()
- val registeredEdges: MutableSet = graph.edges.toMutableSet()
+ private val registeredEdges: MutableSet = graph.edges.toMutableSet()
+ // this field is required for visualization
+ private val allExplicitEdges: MutableSet = graph.edges.toMutableSet()
+
+ val allEdges: Set