Commit 5cf2285c authored by ISWB Prasetya's avatar ISWB Prasetya
Browse files

reimplementing progressive prefixes generation.

parent 997d6034
......@@ -154,39 +154,7 @@ public class G2 {
public void startTimeBudget(long timebudget) {
timebudgetTracker.start(timebudget);
}
int prefixRefinementCount = 0 ;
/**
* Generate the prefixes for ADT testing of the CUT.
*/
protected void refinePrefixes() {
Integer K = config.numberOfPrefixes ;
if (K==null) {
int h = 0 ;
// if (g2sg.staticInfo != null) h = g2sg.staticInfo.allConstants.length ;
K = 50 ;
}
if (g2sg.getPrefixes() == null) {
//System.out.println(">>> here, K="+K);
g2sg.incrementallyGeneratePrefixes(K,10,50,config.maxPrefixLength,config.maxObjectDepth) ;
}
else {
int currentSize = g2sg.getPrefixes().suite.size() ;
int nextSize = Math.min(600,currentSize+50) ;
g2sg.incrementallyRefinePrefixes(10,nextSize,config.maxPrefixLength);
}
prefixRefinementCount++ ;
t3log.info("=== Generating/refining prefixes of "
+ g2sg.scope.CUT.getName()
+ ", generation: " + (prefixRefinementCount - 1)
+ ", size: " + g2sg.getPrefixes().suite.size()
+ ", cov: " + g2sg.currentPrefixes.coverage
+ ", #tobjs: " + g2sg.currentPrefixes.tobjs.size()
);
}
/**
* Generate test suites for each method/constructor (target) of the CUT. One suite
* is generated for each target, and will be immediately saved.
......@@ -209,37 +177,44 @@ public class G2 {
// programming.
// DROPPED!!!
// int numberOfCPUcores = config.numberOfCPUcores ;
int numberOfCPUcores = 1 ;
int prefixRefinementCount = 0 ;
int prefixStagnationCount = 0 ;
while (!worklist.isEmpty()) {
if (worklist.targets.size() < numberOfCPUcores) {
if (worklist.targets.size() == 0) {
// the first time, this will generate the prefixes, upon the next iterations,
// this will refine the prefixes each time the targetlist is emptied (more precisely, has less targets than
// the number of cores).
refinePrefixes() ;
}
// take few targets, and refine them in parallel, if we have multiple CPU cores:
List<SingleTarget> work = new LinkedList<SingleTarget>() ;
for(int k=0; k<numberOfCPUcores ; k++) {
SingleTarget target = worklist.getNext(remaining/budget) ;
if (target == null) break ;
work.add(target) ;
}
work.parallelStream().map(
target -> {
target.refine() ;
worklist.evaluateAndPutBack(target) ;
// this will refine the prefixes each time the targetlist is emptied.
if (prefixStagnationCount < 3) {
prefixRefinementCount++ ;
Integer K = config.numberOfPrefixes ;
if (K==null) K = 50 ;
if (g2sg.getPrefixes() != null) K = Math.min(K,10) ;
int numOfAddedPrefixes = g2sg.incrementallyGeneratePrefixes(K,config.maxPrefixLength,config.maxObjectDepth) ;
if (numOfAddedPrefixes == 0) prefixStagnationCount++ ;
target.saveSuite() ;
// save a minimized version of the test suite; however this seem to drop
// mutation kill rates in some situation; so I will just comment this out.
// Will later make it configurable.
//target.saveMinimizedSuite();
return 0 ;
t3log.info("=== Generating/refining prefixes of "
+ g2sg.scope.CUT.getName()
+ ", generation: " + prefixRefinementCount
+ ", size: " + g2sg.getPrefixes().suite.size()
+ ", cov: " + g2sg.currentPrefixes.coverage
+ ", #tobjs: " + g2sg.currentPrefixes.tobjs.size()
);
}
else {
t3log.warning("Prefix generation for " + g2sg.scope.CUT.getName() + " reaches stagnation. NO further prefixes will be generated.");
}
).count() ; // use count to force the map to be executed
}
SingleTarget target = worklist.getNext(remaining/budget) ;
target.refine() ;
worklist.evaluateAndPutBack(target) ;
target.saveSuite() ;
// save a minimized version of the test suite; however this seem to drop
// mutation kill rates in some situation; so I will just comment this out.
// Will later make it configurable.
//target.saveMinimizedSuite();
remaining = timebudgetTracker.check() ;
}
......
......@@ -387,67 +387,7 @@ public class G2SuiteGen {
if (S.suite.size() == 0) t3log.warning("Cannot generate any test sequence for " + getLongName(c));
return S ;
}
/**
* Generate prefix sequences that basically try to create various states
* of instances of the CUT. Only mutators will be used. Furthermore,
* the sequences should all be non-failing (since they are not really the
* testing sequences, but are only used to create states).
*/
private SUITE generatePrefixes(int N, int maxlength) {
scope.configureForADTtesting();
if (staticInfo != null) {
resetSeededConstants() ;
addSeededSPrimitives(staticInfo.getAllConstansts()) ;
addInstanceOfConstants(staticInfo.getAllInstanceOfClasses()) ;
}
// do not include negative mutators like remove, delete, clear
List<Method> tobeRemoved = new LinkedList<Method>() ;
for (Method m : scope.mutators) {
String name = m.getName().toLowerCase() ;
if (name.contains("remove") || name.contains("delete")
|| name.contains("clear")
|| name.contains("reset"))
tobeRemoved.add(m) ;
}
scope.mutators.removeAll(tobeRemoved) ;
int N_ = Math.max(1,N/maxlength) ;
T3SeqG seqG = new T3SeqG(pool,scope,maxNumberOfStepRetry,valueMG) ;
Generator<SEQ_RT_info,SEQ_RT_info> seqgen ;
SUITE S = new SUITE() ;
SuiteG suitegen = new SuiteG(scope) ;
int k = 0 ;
for (int n=0; n<maxlength ; n++) {
//System.err.println("==>> #S = " + S.suite.size());
seqgen = SequenceWhile(
r -> ! r.isFail(),
seqG.creationGen.nonnull_and_no_exc(),
seqG.no_exc_mutatorsPrefix(fieldUpdateProbability, n, true),
seqG.instrument()
) ;
SUITE T ;
if (n==maxlength-1) {
T = suitegen.run(pool,seqgen,Math.max(1,N-k)) ;
//System.out.println(T.showSuiteStatistics());
S = SUITE.union(S,T) ;
}
else {
T = suitegen.run(pool,seqgen,N_) ;
//System.out.println(T.showSuiteStatistics());
S = SUITE.union(S,T) ;
k += T.suite.size() ;
}
}
S.CUTname = scope.CUT.getName() ;
S.suitename = S.CUTname + "_adtPrefixes" ;
//System.err.println("==>> DELIVERING prefixes #S = " + S.suite.size());
return S ;
}
/**
* Hold the prefixes generated so far, for ADT testing.
......@@ -463,24 +403,29 @@ public class G2SuiteGen {
*/
protected class Prefixes {
SUITE prefixes ;
int size ;
SUITE prefixes = new SUITE() ;
// the list of normalized target-object structures that the prefixes produce
protected List<ObjStructure> tobjs ;
protected List<ObjStructure> tobjs = new LinkedList<ObjStructure>() ;
// code-coverage reached by the current prefixes
protected double coverage = 0 ;
protected int ObjStructureMaxDepth ;
Prefixes(int N0, int maxlength, int ObjStructureMaxDepth) {
prefixes = generatePrefixes(N0,maxlength) ;
prefixes.dropDuplicates();
if (codeCoverage!=null) codeCoverage.clear();
tobjs = ObjStructure.getTargetObjsStrutures(prefixes, scope.CUT, ObjStructureMaxDepth) ;
getCoverage() ;
size = prefixes.suite.size() ;
this.ObjStructureMaxDepth = ObjStructureMaxDepth ;
// will start by generating prefix of length 1, and will increase the length
// progressively
protected int currentLengthToGenerate = 1 ;
protected int crlAccepted = 0 ;
protected int crlRejected = 0 ;
protected int maxlength ;
Prefixes(int maxlength, int ObjStructureMaxDepth) {
prefixes.CUTname = scope.CUT.getName() ;
prefixes.suitename = prefixes.CUTname + "_adtPrefixes" ;
this.maxlength = maxlength ;
this.ObjStructureMaxDepth = ObjStructureMaxDepth ;
}
int size() { return prefixes.suite.size() ; }
private double getCoverage() {
try {
codeCoverage.collectRTdata();
......@@ -492,61 +437,147 @@ public class G2SuiteGen {
return coverage ;
}
private boolean enoughDiversity() {
return crlAccepted >= 10 ;
}
private boolean progressHasStalled() {
return crlRejected >= 5 ;
}
/**
* Refine the prefixes with T. Only prefixes that produce a target object whose
* normalized structure is new will be added. Return true if there is such
* addition, else false.
* Adjust the target prefix-length. If the current length has enough diversity,
* or stagnates, increase the target length. Reset to length 1 if this would
* exceed max-length.
*/
private boolean refine(Pool pool, SUITE T) {
boolean added = false ;
for (SEQ seq : T.suite) {
double coverage0 = coverage ;
if (codeCoverage!=null) codeCoverage.clearRawRTdata();
ObjStructure t = ObjStructure.toObjsStruture(seq, scope.CUT, pool, ObjStructureMaxDepth) ;
getCoverage() ;
if (coverage > coverage0 || ! tobjs.contains(t)) {
tobjs.add(t) ;
prefixes.suite.add(seq) ;
added = true ;
size++ ;
}
private void adjustTargetLengthAsNeeded() {
boolean enoughDiversity = enoughDiversity() ;
boolean stagnated = progressHasStalled() ;
int oldlength = currentLengthToGenerate ;
if (enoughDiversity || stagnated) {
currentLengthToGenerate++ ;
if (currentLengthToGenerate > maxlength) currentLengthToGenerate = 1 ;
crlAccepted = 0 ;
crlRejected = 0 ;
if (enoughDiversity)
System.err.println(">>> Prefix generation at length " + oldlength
+ " has enough diversity. Adjusting target length to "
+ currentLengthToGenerate) ;
if (stagnated)
System.err.println(">>> Prefix generation at length " + oldlength
+ " stagnated. Adjusting target length to "
+ currentLengthToGenerate) ;
}
return added ;
}
/**
* Refine the current set of prefixes by generating N new prefixes. Only
* prefixes that produce "different" tobj or adds in code coverage will
* be added to the collection; so it is possible that less that N prefixes
* are added; or none at all.
*
* The algorithm starts by generating prefixes of length 1 and will progressively
* generate longer prefixes if either it thinks it has produce enough variation
* for the current length, or if the generation has stagnated.
*
* If maximum length is reached and we reach stagnation, we reset the legth
* to 1.
*/
private int refine(int N) {
// prepare the scope
scope.configureForADTtesting();
if (staticInfo != null) {
resetSeededConstants() ;
addSeededSPrimitives(staticInfo.getAllConstansts()) ;
addInstanceOfConstants(staticInfo.getAllInstanceOfClasses()) ;
}
// do not include negative mutators like remove, delete, clear
List<Method> tobeRemoved = new LinkedList<Method>() ;
for (Method m : scope.mutators) {
String name = m.getName().toLowerCase() ;
if (name.contains("remove") || name.contains("delete")
|| name.contains("clear")
|| name.contains("reset"))
tobeRemoved.add(m) ;
}
scope.mutators.removeAll(tobeRemoved) ;
T3SeqG seqG = new T3SeqG(pool,scope,maxNumberOfStepRetry,valueMG) ;
SuiteG suitegen = new SuiteG(scope) ;
Function<Integer,Generator<SEQ_RT_info,SEQ_RT_info>> seqgen ;
seqgen = length -> SequenceWhile(
r -> ! r.isFail(),
seqG.creationGen.nonnull_and_no_exc(),
seqG.no_exc_mutatorsPrefix(fieldUpdateProbability, length, true),
seqG.instrument()
) ;
Pool cheappool = new Pool() ;
// first reset coverage tracking and rerun the prefixes to restore their
// coverage info
if (codeCoverage!=null) codeCoverage.clearRawRTdata();
for (SEQ seq : prefixes.suite) {
try { seq.exec(scope.CUT,cheappool) ; }
catch (Throwable e) { }
}
int numAdded = 0 ;
int kmax = 3*N ;
for (int k=0; k<kmax && numAdded<N ; k++) {
SUITE T = suitegen.run(pool,seqgen.apply(currentLengthToGenerate-1),1) ;
if (T == null || T.suite.isEmpty()) {
crlRejected++ ;
}
else {
// check if the prefix generate something new; add if it does:
SEQ seq = T.suite.get(0) ;
double coverage0 = coverage ;
ObjStructure t = ObjStructure.toObjsStruture(seq, scope.CUT, cheappool, ObjStructureMaxDepth) ;
getCoverage() ;
if (coverage > coverage0 || ! tobjs.contains(t)) {
//System.out.println("Adding. Cov: " + coverage + ", old cov: " + coverage0) ;
tobjs.add(t) ;
prefixes.suite.add(seq) ;
crlAccepted++ ;
numAdded++ ;
}
else {
//System.out.println("Reject. Cov: " + coverage + ", old cov: " + coverage0) ;
crlRejected++ ;
}
}
adjustTargetLengthAsNeeded() ;
}
return numAdded ;
}
}
/**
* This will generate prefixes iteratively using generatePrefixes. In the first round,
* N0 prefixes will be generated. Next round, N will be generated, but only those prefixes
* that produce a new normalized objStructure are added. If for two successive rounds no
* new prefixes can be added, the iteration stops. We will also stop adding prefixes
* if we already have maxN of them.
* This will generate up to N prefixes iteratively. It returns the number
* of prefixes it manages to generate.
*/
public void incrementallyGeneratePrefixes(int N0, int N, int maxN, int maxlength, int maxdepth) {
if (currentPrefixes == null && N0!=0) {
currentPrefixes = new Prefixes(N0,maxlength,maxdepth) ;
public int incrementallyGeneratePrefixes(int N, int maxlength, int maxdepth) {
System.err.println(">>> invoking incrementallyGeneratePrefixes...") ;
if (currentPrefixes == null) {
currentPrefixes = new Prefixes(maxlength,maxdepth) ;
}
System.err.println(">>> incrementallyGeneratePrefixes START, " + N0 + "/" + N + "/" + maxN) ;
int changed = 2 ;
Pool pool = new Pool() ;
while (changed>0 && currentPrefixes.size<maxN) {
System.err.println(">>> #current prefixes=" + currentPrefixes.size) ;
SUITE T = generatePrefixes(N,maxlength) ;
boolean added = currentPrefixes.refine(pool,T) ;
if (added) changed = 2 ;
else changed-- ;
else {
currentPrefixes.maxlength = maxlength ;
currentPrefixes.ObjStructureMaxDepth = maxdepth ;
}
System.err.println(">>> incrementallyGeneratePrefixes DONE") ;
}
/**
* Incrementally refine current prefixes. This assume current-prefixes are not
* null.
*/
public void incrementallyRefinePrefixes(int N, int maxN, int maxlength) {
incrementallyGeneratePrefixes(0,N,maxN,maxlength,0) ;
int added = currentPrefixes.refine(N) ;
if(added == 0) {
System.err.println(">>> incrementallyGeneratePrefixes DONE; FAIL to add any.") ;
}
else {
System.err.println(">>> incrementallyGeneratePrefixes DONE. Adding " + added
+ " prefixes. New size: " + currentPrefixes.size()) ;
}
return added ;
}
public SUITE generateSuiteForASingleMethod(SUITE prefixes, String mname, int K) {
......@@ -634,7 +665,8 @@ public class G2SuiteGen {
g2.maxSuffixLength = 0 ;
g2.regressionMode = true ;
//SUITE S = g2.generatePrefixes(200,3) ;
g2.incrementallyGeneratePrefixes(10,10,1000,3,5) ;
g2.incrementallyGeneratePrefixes(40,4,5) ;
//g2.incrementallyGeneratePrefixes(10,4,5) ;
SUITE S = g2.getPrefixes() ;
System.out.println(S.showSuiteStatistics());
System.out.println("** Variations: " + ObjStructure.countDifferentTargetObjs(S,CUT,5)) ;
......
......@@ -14,7 +14,7 @@ public class Test_G2SuiteGen_forCUTwith_constants {
g2.regressionMode = true ;
int N0 = Math.min(500, Math.max(10, g2.staticInfo.allConstants.length * 20)) ;
System.out.println(">> N0 = " + N0);
g2.incrementallyGeneratePrefixes(N0,10,1000,1,5) ;
g2.incrementallyGeneratePrefixes(N0,1,5) ;
SUITE S = g2.getPrefixes() ;
System.out.println(S.showSuiteStatistics());
System.out.println("** Variations: " + ObjStructure.countDifferentTargetObjs(S,CUT,5)) ;
......
......@@ -16,7 +16,7 @@ public class Test_G2SuiteGen_forSingleMethod {
g2.maxSuffixLength = 0 ;
g2.regressionMode = true ;
//SUITE S = g2.generatePrefixes(200,3) ;
g2.incrementallyGeneratePrefixes(10,10,1000,3,5) ;
g2.incrementallyGeneratePrefixes(10,3,5) ;
SUITE S = g2.getPrefixes() ;
System.out.println(S.showSuiteStatistics());
System.out.println("** Variations: " + ObjStructure.countDifferentTargetObjs(S,CUT,5)) ;
......
......@@ -14,7 +14,7 @@ public class Test_G2SuiteGen_prefixes {
g2.maxSuffixLength = 0 ;
g2.regressionMode = true ;
//SUITE S = g2.generatePrefixes(200,3) ;
g2.incrementallyGeneratePrefixes(10,10,1000,3,5) ;
g2.incrementallyGeneratePrefixes(10,3,5) ;
SUITE S = g2.getPrefixes() ;
System.out.println(S.showSuiteStatistics());
System.out.println("** Variations: " + ObjStructure.countDifferentTargetObjs(S,CUT,5)) ;
......
......@@ -12,9 +12,9 @@ public class Test_G2_forTriangle {
config.dirToSaveSuites = "/Users/iswbprasetya/tmp/t3" ;
config.dirOfStaticInfo = "/Users/iswbprasetya/tmp/t3" ;
config.generateJunitForEachSuite = false ;
config.maxPrefixLength = 10 ;
config.maxPrefixLength = 6 ;
config.maxSuffixLength = 1 ;
config.numberOfPrefixes = 60 ;
config.numberOfPrefixes = 40 ;
// config.refinementHeuristic="evo" ;
return config ;
}
......@@ -38,7 +38,7 @@ public class Test_G2_forTriangle {
}
static void genWithG2() throws Exception {
G2.generateSuites("Sequenic.T3.Examples.Triangle1",config(),300000) ;
G2.generateSuites("Sequenic.T3.Examples.Triangle1",config(),3000000) ;
}
public static void replayG2() throws Throwable {
......@@ -48,7 +48,7 @@ public class Test_G2_forTriangle {
static public void main(String[] args) throws Throwable {
//test_one_bareG2() ;
//test_two_bareG2() ;
genWithG2() ;
//replayG2() ;
//genWithG2() ;
replayG2() ;
}
}
......@@ -8,19 +8,22 @@ public class Triangle1 {
private float z = 0 ;
public Triangle1(){
//System.out.println("Creating a triangle");
//System.out.println(" reating a triangle");
}
public void setX(float x) {
if (x<=0) throw new IllegalArgumentException() ;
this.x = x ;
//System.out.println(" SetX");
}
public void setY(float y) {
if (y<=0) throw new IllegalArgumentException() ;
this.y = y ;
//System.out.println(" SetY");
}
public void setZ(float z) {
if (z<=0) throw new IllegalArgumentException() ;
this.z = z ;
//System.out.println(" SetZ");
}
public boolean isTriangle() {
if (x >= y+z) return false ;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment