mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
jetCheck: don't retain generators to avoid OOME by capturing user objects
This commit is contained in:
@@ -12,7 +12,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
class NodeId {
|
||||
private final AtomicInteger counter;
|
||||
final int number;
|
||||
@Nullable final Generator<?> generator;
|
||||
@Nullable final Integer generatorHash;
|
||||
|
||||
NodeId(@NotNull Generator<?> generator) {
|
||||
this(new AtomicInteger(), generator);
|
||||
@@ -20,7 +20,7 @@ class NodeId {
|
||||
|
||||
private NodeId(AtomicInteger counter, @Nullable Generator<?> generator) {
|
||||
this.counter = counter;
|
||||
this.generator = generator;
|
||||
this.generatorHash = generator == null ? null : generator.getGeneratorFunction().hashCode();
|
||||
number = counter.getAndIncrement();
|
||||
}
|
||||
|
||||
|
||||
@@ -137,14 +137,14 @@ class StructureNode extends StructureElement {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void findChildrenWithGenerator(@NotNull Generator<?> generator, List<StructureNode> result) {
|
||||
private void findChildrenWithGenerator(int generatorHash, List<StructureNode> result) {
|
||||
for (StructureElement child : children) {
|
||||
if (child instanceof StructureNode) {
|
||||
Generator<?> childGen = child.id.generator;
|
||||
if (childGen != null && generator.getGeneratorFunction().equals(childGen.getGeneratorFunction())) {
|
||||
Integer childGen = child.id.generatorHash;
|
||||
if (childGen != null && generatorHash == childGen.intValue()) {
|
||||
result.add((StructureNode)child);
|
||||
} else {
|
||||
((StructureNode)child).findChildrenWithGenerator(generator, result);
|
||||
((StructureNode)child).findChildrenWithGenerator(generatorHash, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,9 +152,9 @@ class StructureNode extends StructureElement {
|
||||
|
||||
@Nullable
|
||||
private ShrinkStep shrinkRecursion() {
|
||||
if (id.generator != null) {
|
||||
if (id.generatorHash != null) {
|
||||
List<StructureNode> sameGeneratorChildren = new ArrayList<>();
|
||||
findChildrenWithGenerator(id.generator, sameGeneratorChildren);
|
||||
findChildrenWithGenerator(id.generatorHash, sameGeneratorChildren);
|
||||
return tryReplacing(sameGeneratorChildren, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ package org.jetbrains.jetCheck;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -131,6 +132,26 @@ public class StatefulGeneratorTest extends PropertyCheckerTestCase {
|
||||
sb.delete(start, end);
|
||||
};
|
||||
}
|
||||
|
||||
private ImperativeCommand heavyCommand() {
|
||||
Object[] heavyObject = new Object[100_000];
|
||||
heavyObject[42] = new Object();
|
||||
return new ImperativeCommand() {
|
||||
@Override
|
||||
public void performCommand(@NotNull Environment env) {}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + Arrays.toString(heavyObject);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void testDontFailByOutOfMemoryDueToLeakingObjectsPassedIntoGenerators() {
|
||||
PropertyChecker.customized().checkScenarios(() -> env ->
|
||||
env.executeCommands(from(data -> data.generate(sampledFrom(heavyCommand(), heavyCommand(), heavyCommand())))));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class InsertChar {
|
||||
|
||||
Reference in New Issue
Block a user