Description
Description
Processing of Enum
types may result in ClassCastException
, as UtEnumConstantModel
is incorrectly cast to UtReferenceModel
in several situations, in particular:
ArrayObjectWrappers.kt
:AssociativeArrayWrapper.value()
(the location related to the reproducible example below).CollectionWrappers.kt
:constructKeysAndValues()
(a similar type cast).
To Reproduce
Generate the test suite for the MapExamples
class.
Color.java
:
public enum Color {
UNDEFINED,
RED,
YELLOW,
GREEN
}
MapExamples.java
:
public class MapExamples {
public Color[] transduce(@NotNull Color[] inputs, @NotNull HashMap<Color, Color> fst) {
if (inputs.length > 0) {
Color[] result = new Color[inputs.length];
for (int i = 0; i < inputs.length; i++) {
result[i] = fst.getOrDefault(inputs[i], Color.UNDEFINED);
}
return result;
} else {
return new Color[0];
}
}
public Color[] trafficLightTransduce(@NotNull Color[] inputs) {
HashMap<Color, Color> trafficLight = new HashMap<>();
trafficLight.put(Color.RED, Color.GREEN);
trafficLight.put(Color.GREEN, Color.YELLOW);
trafficLight.put(Color.YELLOW, Color.RED);
return transduce(inputs, trafficLight);
}
}
Expected behavior
Test suite is generated, no ClassCastException
errors are reported.
Actual behavior
No tests are generated, the plugin fails with the following exception:
java.lang.ClassCastException: class org.utbot.framework.plugin.api.UtEnumConstantModel cannot be cast to class org.utbot.framework.plugin.api.UtReferenceModel (org.utbot.framework.plugin.api.UtEnumConstantModel and org.utbot.framework.plugin.api.UtReferenceModel are in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @56d6d8d8)
at org.utbot.engine.AssociativeArrayWrapper.value(ArrayObjectWrappers.kt:382)
at org.utbot.engine.Resolver.resolveObject(Resolver.kt:454)
at org.utbot.engine.Resolver.resolveReferenceValue(Resolver.kt:424)
at org.utbot.engine.Resolver.resolveModel(Resolver.kt:395)
at org.utbot.engine.Resolver.collectFieldModels(Resolver.kt:581)
at org.utbot.engine.MapWrapper.resolveValueModels(CollectionWrappers.kt:309)
at org.utbot.engine.BaseCollectionWrapper.value(CollectionWrappers.kt:108)
at org.utbot.engine.BaseCollectionWrapper.value(CollectionWrappers.kt:99)
at org.utbot.engine.Resolver.resolveObject(Resolver.kt:454)
at org.utbot.engine.Resolver.resolveReferenceValue(Resolver.kt:424)
at org.utbot.engine.Resolver.resolveModel(Resolver.kt:395)
at org.utbot.engine.Resolver.internalResolveModel(Resolver.kt:233)
at org.utbot.engine.Resolver.resolveModels$utbot_framework(Resolver.kt:204)
at org.utbot.engine.UtBotSymbolicEngine$traverseImpl$1.invokeSuspend(UtBotSymbolicEngine.kt:466)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at org.utbot.common.ConcurrencyKt.runBlockingWithCancellationPredicate(Concurrency.kt:38)
at org.utbot.framework.plugin.api.UtBotTestCaseGenerator$generateForSeveralMethods$4.invoke(UtBotTestCaseGenerator.kt:263)
at org.utbot.framework.plugin.api.UtBotTestCaseGenerator$generateForSeveralMethods$4.invoke(UtBotTestCaseGenerator.kt:56)
at org.utbot.common.ConcurrencyKt.runIgnoringCancellationException(Concurrency.kt:47)
at org.utbot.framework.plugin.api.UtBotTestCaseGenerator.generateForSeveralMethods(UtBotTestCaseGenerator.kt:262)
at org.utbot.framework.plugin.api.UtBotTestCaseGenerator.generateForSeveralMethods$default(UtBotTestCaseGenerator.kt:249)
at org.utbot.intellij.plugin.generator.CodeGenerator.generateForSeveralMethods(CodeGenerator.kt:53)
at org.utbot.intellij.plugin.ui.UtTestsDialogProcessor$createTests$2$1.run(UtTestsDialogProcessor.kt:164)
at com.intellij.openapi.progress.impl.CoreProgressManager.startTask(CoreProgressManager.java:442)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.startTask(ProgressManagerImpl.java:114)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcessWithProgressAsynchronously$5(CoreProgressManager.java:493)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$3(ProgressRunner.java:244)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:189)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$12(CoreProgressManager.java:608)
at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:683)
at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:639)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:607)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:60)
at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:176)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$4(ProgressRunner.java:244)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:668)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:665)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:665)
at java.base/java.lang.Thread.run(Thread.java:829)
It is possible that some tests are generated, but a non-empty error suite is generated as well (I encountered this case once but it seems hard to reproduce). See Additional context below for details.
Environment
Mock strategy: Other packages: Mockito
Mock static: No static mocking
Test framework: JUnit5
Additional context
I somehow managed to generate a non-empty test suite with several reported ClassCastException
errors. It seems hard to reproduce (usually the generator just fails, so I am not sure that it is not a version mismatch from my side), but it might be useful to have this log.
public class MapExamplesTest {
///region Test suites for executable collections.MapExamples.transduce
///region SUCCESSFUL EXECUTIONS for method transduce(collections.Color[], java.util.HashMap)
/**
* <pre>
* Test does not iterate {@code for(int i = 0; i < inputs.length; i++) }, executes conditions:
* {@code (inputs.length > 0): False }
* returns from: {@code return new Color[0]; }
* </pre>
*/
@Test
@DisplayName("transduce: inputs.length > 0 : False -> return new Color[0]")
public void testTransduce_InputsLengthLessOrEqualZero() {
MapExamples mapExamples = new MapExamples();
Color[] colorArray = {};
HashMap hashMap = new HashMap();
Color[] actual = mapExamples.transduce(colorArray, hashMap);
Color[] expected = {};
int expectedSize = expected.length;
assertEquals(expectedSize, actual.length);
assertTrue(deepEquals(expected, actual));
}
/**
* <pre>
* Test executes conditions:
* {@code (inputs.length > 0): True }
* iterates the loop {@code for(int i = 0; i < inputs.length; i++) } once.
* Test then returns from: {@code return result; }
* </pre>
*/
@Test
@DisplayName("transduce: inputs.length > 0 : True -> return result")
public void testTransduce_InputsLengthGreaterThanZero() throws ClassNotFoundException, Exception {
Color prevUNDEFINED = Color.UNDEFINED;
try {
Color undefined = Color.UNDEFINED;
Class colorClazz = Class.forName("collections.Color");
setStaticField(colorClazz, "UNDEFINED", undefined);
MapExamples mapExamples = new MapExamples();
Color[] colorArray = {null};
HashMap hashMap = new HashMap();
Color[] actual = mapExamples.transduce(colorArray, hashMap);
Color[] expected = new Color[1];
Color color = Color.UNDEFINED;
expected[0] = color;
int expectedSize = expected.length;
assertEquals(expectedSize, actual.length);
assertTrue(deepEquals(expected, actual));
Color finalColorArray0 = colorArray[0];
assertNull(finalColorArray0);
} finally {
setStaticField(Color.class, "UNDEFINED", prevUNDEFINED);
}
}
///endregion
///region Errors report for transduce
public void testTransduce_errors() {
// Couldn't generate some tests. List of errors:
//
// 18 occurrences of:
/* class org.utbot.framework.plugin.api.UtEnumConstantModel cannot be cast to class org.utbot.framework.plugin.api.UtReferenceModel (org.utbot.framework.plugin.api.UtEnumConstantModel and
org.utbot.framework.plugin.api.UtReferenceModel are in unnamed module of loader com.intellij.ide.plugins.cl.PluginClassLoader @33114743) */
}
///endregion
///endregion
///region Test suites for executable collections.MapExamples.trafficLightTransduce
///region SUCCESSFUL EXECUTIONS for method trafficLightTransduce(collections.Color[])
/**
* <pre>
* Test calls MapExamples::transduce,
* there it does not iterate {@code for(int i = 0; i < inputs.length; i++) }, executes conditions:
* {@code (inputs.length > 0): False }
* returns from: {@code return new Color[0]; }
*
* Test afterwards returns from: {@code return transduce(inputs, trafficLight); }
* </pre>
*/
@Test
@DisplayName("trafficLightTransduce: inputs.length > 0 : False -> return new Color[0]")
public void testTrafficLightTransduce_InputsLengthLessOrEqualZero() throws ClassNotFoundException, Exception {
Color prevRED = Color.RED;
Color prevGREEN = Color.GREEN;
Color prevYELLOW = Color.YELLOW;
try {
Color red = Color.RED;
Class colorClazz = Class.forName("collections.Color");
setStaticField(colorClazz, "RED", red);
Color green = Color.GREEN;
setStaticField(colorClazz, "GREEN", green);
Color yellow = Color.YELLOW;
setStaticField(colorClazz, "YELLOW", yellow);
MapExamples mapExamples = new MapExamples();
Color[] colorArray = {};
Color[] actual = mapExamples.trafficLightTransducer(colorArray);
Color[] expected = {};
int expectedSize = expected.length;
assertEquals(expectedSize, actual.length);
assertTrue(deepEquals(expected, actual));
} finally {
setStaticField(Color.class, "RED", prevRED);
setStaticField(Color.class, "GREEN", prevGREEN);
setStaticField(Color.class, "YELLOW", prevYELLOW);
}
}
/**
* <pre>
* Test calls MapExamples::transduce,
* there it executes conditions:
* {@code (inputs.length > 0): True }
* iterates the loop {@code for(int i = 0; i < inputs.length; i++) } once.
* Test then returns from: {@code return result; }
*
* Test next returns from: {@code return transduce(inputs, trafficLight); }
* </pre>
*/
@Test
@DisplayName("trafficLightTransduce: inputs.length > 0 : True -> return result")
public void testTrafficLightTransduce_InputsLengthGreaterThanZero() throws ClassNotFoundException, Exception {
Color prevRED = Color.RED;
Color prevGREEN = Color.GREEN;
Color prevYELLOW = Color.YELLOW;
Color prevUNDEFINED = Color.UNDEFINED;
try {
Color red = Color.RED;
Class colorClazz = Class.forName("collections.Color");
setStaticField(colorClazz, "RED", red);
Color green = Color.GREEN;
setStaticField(colorClazz, "GREEN", green);
Color yellow = Color.YELLOW;
setStaticField(colorClazz, "YELLOW", yellow);
Color undefined = Color.UNDEFINED;
setStaticField(colorClazz, "UNDEFINED", undefined);
MapExamples mapExamples = new MapExamples();
Color[] colorArray = {null};
Color[] actual = mapExamples.trafficLightTransducer(colorArray);
Color[] expected = new Color[1];
Color color = Color.UNDEFINED;
expected[0] = color;
int expectedSize = expected.length;
assertEquals(expectedSize, actual.length);
assertTrue(deepEquals(expected, actual));
Color finalColorArray0 = colorArray[0];
assertNull(finalColorArray0);
} finally {
setStaticField(Color.class, "RED", prevRED);
setStaticField(Color.class, "GREEN", prevGREEN);
setStaticField(Color.class, "YELLOW", prevYELLOW);
setStaticField(Color.class, "UNDEFINED", prevUNDEFINED);
}
}
///endregion
///endregion
}
Metadata
Metadata
Assignees
Type
Projects
Status