-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Controlling size for nested data structures? #556
Comments
@mikera Thanks for checking out junit-quickcheck. I don't plan to develop on it any further -- you may want to investigate Jqwik by @jqwik-team. That said, I'd be interested to check out your custom generators. Can you post some code? |
Thanks for the reference, I will take a look! Here's an example of a fairly minimal generator that blows up (stack overflow) while creating a proportion of nested instances of the same type (ArrayLists of ArrayLists and Longs): import java.util.ArrayList;
import com.pholser.junit.quickcheck.generator.GenerationStatus;
import com.pholser.junit.quickcheck.generator.Generator;
import com.pholser.junit.quickcheck.random.SourceOfRandomness;
/**
* Generator for arbitrary trees of Longs
*/
public class BadListGen extends Generator<Object> {
public BadListGen() {
super(Object.class);
}
@Override
public Object generate(SourceOfRandomness r, GenerationStatus status) {
int size=status.size()+1;
int type = r.nextInt(10);
switch (type) {
case 0:
int n = r.nextInt(size);
ArrayList<Object> al=new ArrayList<>();
for (int i=0; i<n; i++) {
al.add(generate(r,status));
}
return al;
default:
Long l=r.nextLong(-size, size);
return l;
}
}
} Ideally, I think the size in the nested call to generate needs to be reduced to something like |
@mikera Ah yes, I see what you mean. Sadly, I didn't make accessible |
@mikera What do you think about something like this? public class BadListGen extends Generator<Object> {
public BadListGen() {
super(Object.class);
}
@Override
public Object generate(SourceOfRandomness r, GenerationStatus status) {
List<Object> root = new ArrayList<>();
for (int i = 0; i < status.size(); ++i) {
root.add(_generate(r, status.size(), 1));
}
return root;
}
private Object _generate(SourceOfRandomness r, int size, int level) {
int type = r.nextInt(10);
if (type == 0) {
int numberOfChildren = size == 0 ? 0 : r.nextInt(size);
List<Object> children = new ArrayList<>();
for (int i = 0; i < numberOfChildren; i++) {
children.add(_generate(r, size / (level + 1), level + 1));
}
return children;
}
return r.nextLong(-size, size);
}
} |
Thanks @pholser for taking a look - your suggestion works well in simple cases Only slight challenge is if the generator is parameterised and needs to generate something (e.g. leaf nodes) with a generic Perhaps an interesting research topic for someone would be exploring how test data generators can be structured to provide provable |
Love the library! It is proving very useful. Quick question....
SITUATION: I'm writing some custom generators for data structures that potentially need to generate multiple nested structures of the same type.
PROBLEM: There is a certain threshold where the sizes of the generated data structures seem to explode exponentially, probably because the expected number of children increases at each level (which in turn have a larger expected number of children themselves...)
QUESTION: Is there a good way to control the sizes of nested structures? Ideally if I am generating a data structure of size
n
withm
children, it seems like it would be sensible for each child to be generated with sizen/m
but it's not quite clear how to do this?The text was updated successfully, but these errors were encountered: