Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Prasetya, S.W.B. (Wishnu)
t3
Commits
85ebce29
Commit
85ebce29
authored
Jan 31, 2019
by
Prasetya, S.W.B. (Wishnu)
Browse files
Merge branch 'new-treatement-for-interface-and-abs' into 'master'
New treatment for interface and abs See merge request
!1
parents
5cf2285c
5be16a2b
Changes
18
Hide whitespace changes
Inline
Side-by-side
src/Sequenic/T3/DerivativeSuiteGens/Gen2/CustomGenDSL.java
0 → 100644
View file @
85ebce29
package
Sequenic.T3.DerivativeSuiteGens.Gen2
;
import
static
Sequenic
.
T3
.
Generator
.
GenCombinators
.
OneOfVal
;
import
java.io.Serializable
;
import
Sequenic.T3.Generator.Generator
;
import
Sequenic.T3.JavaType.JTypeUtils
;
import
Sequenic.T3.Sequence.Datatype.PARAM
;
public
class
CustomGenDSL
{
static
boolean
ofOfTheseTypes
(
PARAM
P
,
Class
...
cls
)
{
Class
C
=
JTypeUtils
.
getTopClass
(
P
.
ty
)
;
for
(
Class
D
:
cls
)
{
if
(
C
==
D
)
return
true
;
}
return
false
;
}
public
static
Generator
<
PARAM
,
Serializable
>
OneOfVal_
(
Float
...
f
)
{
Serializable
[]
f_
=
f
;
Generator
<
PARAM
,
Serializable
>
gen
=
OneOfVal
(
f_
)
;
return
gen
.
If
(
P
->
ofOfTheseTypes
(
P
,
Float
.
class
,
Float
.
TYPE
))
;
}
public
static
Generator
<
PARAM
,
Serializable
>
OneOfVal_
(
Integer
...
f
)
{
Serializable
[]
f_
=
f
;
Generator
<
PARAM
,
Serializable
>
gen
=
OneOfVal
(
f_
)
;
return
gen
.
If
(
P
->
ofOfTheseTypes
(
P
,
Integer
.
class
,
Integer
.
TYPE
))
;
}
public
static
Generator
<
PARAM
,
Serializable
>
OneOfVal_
(
String
...
f
)
{
Serializable
[]
f_
=
f
;
Generator
<
PARAM
,
Serializable
>
gen
=
OneOfVal
(
f_
)
;
return
gen
.
If
(
P
->
ofOfTheseTypes
(
P
,
String
.
class
))
;
}
}
src/Sequenic/T3/DerivativeSuiteGens/Gen2/G2.java
View file @
85ebce29
...
...
@@ -33,6 +33,13 @@ import Sequenic.T3.Pool;
import
Sequenic.T3.SimpleClassLoader
;
import
Sequenic.T3.Sequence.Datatype.*
;
/**
* This provides top-level APIs to invoke G2 generator. Use the static method:
*
* generateSuites(CUTname,config,timebudget) ... the budget is in ms.
*
*/
public
class
G2
{
/**
...
...
@@ -97,13 +104,14 @@ public class G2 {
static
public
class
TimeBudgetException
extends
Exception
{
}
/**
* Create an instance of G2 test suites generator. CUT has to be a concrete class
* (it should not be an interface nor an abstract class).
* @throws Exception
* Create an instance of G2 test suites generator. Typically, the CUT is a concrete
* class (it is not an interface or an abstract class). If an interface or an abstract
* class is given as the CUT, it may still contain concrete static methods, which we
* can test; so in these cases we will target them.
*/
protected
G2
(
String
CUTname
,
G2Config
config
)
throws
Exception
{
this
.
config
=
config
;
g2sg
=
new
G2SuiteGen
(
CUTname
,
config
.
CUTrootDir
,
config
.
useCoverageGuidance
,
config
.
useStaticInfo
,
config
.
dirOfStaticInfo
)
;
g2sg
=
new
G2SuiteGen
(
CUTname
,
config
.
CUTrootDir
,
config
.
useCoverageGuidance
,
config
.
useStaticInfo
,
config
.
dirOfStaticInfo
,
config
.
customPrimitivesGenerator
)
;
g2sg
.
regressionMode
=
config
.
regressionMode
;
g2sg
.
injectOracles
=
config
.
injectOracles
;
g2sg
.
maxSuffixLength
=
config
.
maxSuffixLength
;
...
...
@@ -127,28 +135,38 @@ public class G2 {
else
t
=
new
SingleTarget
(
config
,
g2sg
,
m
)
;
worklist
.
addTarget
(
t
);
}
g2sg
.
scope
.
configureForADTtesting
();
for
(
Constructor
co
:
g2sg
.
scope
.
constructors
)
{
SingleTarget
t
;
if
(
config
.
refinementHeuristic
.
equals
(
"evo"
))
t
=
new
EvoSingleTarget
(
config
,
g2sg
,
co
)
;
else
t
=
new
SingleTarget
(
config
,
g2sg
,
co
)
;
//worklist.addTarget(t);
}
for
(
Method
m
:
g2sg
.
scope
.
methods
)
{
if
(
Modifier
.
isStatic
(
m
.
getModifiers
()))
continue
;
SingleTarget
t
;
if
(
config
.
refinementHeuristic
.
equals
(
"evo"
))
t
=
new
EvoSingleTarget
(
config
,
g2sg
,
m
)
;
else
t
=
new
SingleTarget
(
config
,
g2sg
,
m
)
;
worklist
.
addTarget
(
t
);
if
(!
g2sg
.
scope
.
CUT
.
isInterface
()
&&
!
Modifier
.
isAbstract
(
g2sg
.
scope
.
CUT
.
getModifiers
()))
{
// set targets for ADT testing; only when the CUT is concrete:
g2sg
.
scope
.
configureForADTtesting
();
for
(
Constructor
co
:
g2sg
.
scope
.
constructors
)
{
SingleTarget
t
;
if
(
config
.
refinementHeuristic
.
equals
(
"evo"
))
t
=
new
EvoSingleTarget
(
config
,
g2sg
,
co
)
;
else
t
=
new
SingleTarget
(
config
,
g2sg
,
co
)
;
//worklist.addTarget(t);
}
for
(
Method
m
:
g2sg
.
scope
.
methods
)
{
if
(
Modifier
.
isStatic
(
m
.
getModifiers
()))
continue
;
SingleTarget
t
;
if
(
config
.
refinementHeuristic
.
equals
(
"evo"
))
t
=
new
EvoSingleTarget
(
config
,
g2sg
,
m
)
;
else
t
=
new
SingleTarget
(
config
,
g2sg
,
m
)
;
worklist
.
addTarget
(
t
);
}
}
t3log
.
info
(
"Creating "
+
printTargets
())
;
}
private
String
printTargets
()
{
StringBuilder
s
=
new
StringBuilder
()
;
s
.
append
(
"#worklist="
+
worklist
.
waiting
.
size
()
+
", targets: "
)
;
s
.
append
(
"G2 generator targeting "
+
g2sg
.
scope
.
CUT
.
getName
())
;
s
.
append
(
", #worklist="
+
worklist
.
waiting
.
size
()
+
", targets: "
)
;
for
(
SingleTarget
target
:
worklist
.
waiting
)
{
target
.
maxNumberOfRefinement
=
config
.
maxNumberOfRefinements_ofEachTarget
;
target
.
minimumCovTobeHappy
=
config
.
minimumCovTobeHappy_ofEachTarget
;
s
.
append
(
"\n "
+
target
.
getName
()
+
"("
+
target
.
getNumOfParams
()
+
")"
)
;
}
t3log
.
info
(
"Creating G2 targeting "
+
g2sg
.
scope
.
CUT
.
getName
()
+
", "
+
s
.
toString
()
);
return
s
.
toString
()
;
}
public
void
startTimeBudget
(
long
timebudget
)
{
...
...
@@ -165,6 +183,11 @@ public class G2 {
* The whole process will keep going, until it runs out time budget.
*/
protected
void
generateAndRefine
()
throws
TimeBudgetException
,
InterruptedException
{
if
(
worklist
.
isEmpty
())
{
t3log
.
info
(
""
+
g2sg
.
scope
.
CUT
.
getName
()
+
" induces no target, so NO TEST SUITE is generated."
)
;
return
;
}
// DON't do shut down here!! --> JacocoInstrumenter.shutDownJacocoLogger();
double
budget
=
Math
.
max
(
1
,
timebudgetTracker
.
getBudget
())
;
double
remaining
=
timebudgetTracker
.
check
()
;
...
...
@@ -180,35 +203,51 @@ public class G2 {
int
prefixRefinementCount
=
0
;
int
prefixStagnationCount
=
0
;
int
stagnationLimit
=
3
;
boolean
generateMorePrefix
=
worklist
.
hasADTtarget
()
;
while
(!
worklist
.
isEmpty
())
{
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.
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
++
;
if
(
generateMorePrefix
&&
prefixStagnationCount
<
stagnationLimit
)
{
prefixRefinementCount
++
;
Integer
K
=
config
.
numberOfPrefixes
;
if
(
K
==
null
)
K
=
50
;
if
(
g2sg
.
getPrefixes
()
!=
null
)
K
=
Math
.
min
(
K
,
10
)
;
Integer
numOfAddedPrefixes
=
g2sg
.
incrementallyGeneratePrefixes
(
K
,
config
.
maxPrefixLength
,
config
.
maxObjectDepth
)
;
// reset this flag to false:
generateMorePrefix
=
false
;
if
(
numOfAddedPrefixes
==
null
)
{
// cannot generate prefixes because CUT has no constructor/factory,
// we should now remove all ADT targets because we can't solve them anyway
worklist
.
removeADTtargets
();
t3log
.
info
(
"Since "
+
g2sg
.
scope
.
CUT
.
getName
()
+
" can't be instantiated, we now DROP all ADT targets."
)
;
// go back to the loop-head again:
continue
;
}
t3log
.
info
(
"=== Generating/refining prefixes of "
if
(
numOfAddedPrefixes
==
0
)
{
prefixStagnationCount
++
;
if
(
prefixStagnationCount
>=
stagnationLimit
)
{
t3log
.
warning
(
"Prefix generation for "
+
g2sg
.
scope
.
CUT
.
getName
()
+
" reaches stagnation. NO further prefixes will be generated."
);
}
}
t3log
.
info
(
"=== Generating/refining prefixes of "
+
g2sg
.
scope
.
CUT
.
getName
()
+
", generation: "
+
prefixRefinementCount
+
", size: "
+
g2sg
.
getPrefixes
().
suite
.
size
()
+
". Generation: "
+
prefixRefinementCount
+
", adding: "
+
numOfAddedPrefixes
+
", tot-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."
);
}
}
SingleTarget
target
=
worklist
.
getNext
(
remaining
/
budget
)
;
target
.
refine
()
;
worklist
.
evaluateAndPutBack
(
target
)
;
boolean
targetSolved
=
worklist
.
evaluateAndPutBack
(
target
)
;
if
(!
targetSolved
&&
target
.
isADT
&&
target
.
target
instanceof
Method
)
{
// a method-ADT target cannot be solved. Signal need to generate more prefixes.
// Note that a constructor-target does not need prefix.
generateMorePrefix
=
true
;
}
target
.
saveSuite
()
;
// save a minimized version of the test suite; however this seem to drop
...
...
@@ -227,14 +266,28 @@ public class G2 {
/**
* Use this factory method to construct instances of G2 to generate test
* suites for a given CUT.
* If the CUT is not concrete (it is an interface or abstract) then
* the method tries to find a concrete implementation of the CUT and target
* this implementation instead. If there are multiple implementations, one
* will be selected randomly.
* There are three special cases:
*
* (1) CUT is an interface. It may have static methods, which are then concrete.
* G2 will then target these methods.
*
* (2) CUT is an abstract class. Like Interface, it may gace static methods, which
* must be concrete. G2 will in any case target these methods.
*
* An abstract class may also have some concrete constructors and instance methods.
* These methods cannot be tested directly since Java prevents direct creation of
* instances of an abstract class. We will have to test the CUT indirectly through
* a concrete subclass. Ideally, the tester should provide a proxy subclass that
* will simply pass calls to implemented methods of the CUT, but for now G2 will just
* search for a random implementation of the CUT and targets this implementation instead.
*
* If the CUT has no inner class, then only a single instance of G2 will be
* generated. If it has static inner classes, one instance of G2 will be
* recursively constructed for each such inner class.
* This will create a separate instance of G2, targeting the implementation.
*
* TODO: a tool to generate such a proxy class.
*
* (3) If the CUT has inner classes, and if G2 is configured to chase them, it will
* target these inner classes as well. Fresh instances of G2 will be created for each
* inner class.
*/
static
public
List
<
G2
>
mkG2
(
String
CUTname
,
G2Config
config
)
{
ImplementationMap
imap
=
new
ImplementationMap
(
new
String
[
0
])
;
...
...
@@ -263,49 +316,44 @@ public class G2 {
ImplementationMap
imap
,
ClassLoader
loader
)
{
List
<
G2
>
g2s
=
new
LinkedList
<
G2
>()
;
try
{
Class
CUT
=
loader
.
loadClass
(
CUTname
)
;
boolean
abstractCUT
=
Modifier
.
isAbstract
(
CUT
.
getModifiers
())
;
if
(
CUT
.
isInterface
()
||
abstractCUT
)
{
// if CUT is an interface or abstract, find an implementation:
Class
imp
=
imap
.
getRndImp
(
CUT
)
;
if
(
imp
!=
null
)
{
t3log
.
info
(
CUT
.
getName
()
+
" is abstract or interface; trying to target a concrete implementation instead, namely:"
+
imp
.
getName
());
g2s
.
add
(
new
G2
(
imp
.
getName
(),
config
))
;
}
else
t3log
.
warning
(
CUT
.
getName
()
+
" is abstract or interface; but failed to find an implementation to target!"
);
if
(
abstractCUT
)
{
//Method[] publicmethods = CUT.getMethods() ;
Method
[]
CUTmethods
=
CUT
.
getDeclaredMethods
()
;
for
(
Method
m
:
CUTmethods
)
{
int
m_
=
m
.
getModifiers
()
;
if
(!
Modifier
.
isAbstract
(
m_
)
&&
Modifier
.
isStatic
(
m_
))
{
t3log
.
info
(
CUT
.
getName
()
+
" is abstract, but it has at least one concrete and static method; so we target the class too."
);
g2s
.
add
(
new
G2
(
CUTname
,
config
))
;
break
;
}
}
}
List
<
G2
>
g2s
=
new
LinkedList
<
G2
>()
;
try
{
// First create G2 for the CUT itself. Even if it is non-concrete it may contains concrete
// static classes that we should test
g2s
.
add
(
new
G2
(
CUTname
,
config
))
;
// If CUT is abstract, it may have concrete methods. To test these we need to create
// instances of the CUT. However, an abstract class cannot be instantiated, so we need
// to find a concrete implementation, and test the CUT indirectly through this concrete
// implementation:
Class
CUT
=
loader
.
loadClass
(
CUTname
)
;
if
(!
CUT
.
isInterface
()
&&
Modifier
.
isAbstract
(
CUT
.
getModifiers
()))
{
// if CUT is abstract, find an implementation:
Class
imp
=
imap
.
getRndImp
(
CUT
)
;
if
(
imp
!=
null
)
{
t3log
.
info
(
CUT
.
getName
()
+
" is abstract; we will test indirectly through a concrete implementation, namely:"
+
imp
.
getName
());
G2
g2indirect
=
new
G2
(
imp
.
getName
(),
config
)
;
g2s
.
add
(
g2indirect
)
;
}
else
t3log
.
warning
(
CUT
.
getName
()
+
" is abstract; but failed to find an implementation to target!"
);
}
else
g2s
.
add
(
new
G2
(
CUTname
,
config
))
;
// we additionally constructs instances of G2 for every static inner
// class of the CUT
if
(
config
.
targetStaticInnerClassesToo
)
{
// in some rare case CUT.getDeclaredClasses() may throw java.lang.IllegalAccessError, cannot access superclass...
// can't figure out why; probably classloader issue
for
(
Class
innerC
:
CUT
.
getDeclaredClasses
())
{
// non static inner classes and inherited inner classes are NOT targeted:
// NOTE: well, include them nonetheless...
// if (! Modifier.isStatic(innerC.getModifiers())) continue ;
// if (innerC.getDeclaringClass() != CUT) continue ;
// t3log.info("Found an inner static class " + innerC.getName());
g2s
.
addAll
(
mkG2worker
(
innerC
.
getName
(),
config
,
imap
,
loader
))
;
}
// if configured to do so, we additionally constructs instances of G2 for every static inner
// class of the CUT
if
(
config
.
targetStaticInnerClassesToo
)
{
// in some rare case CUT.getDeclaredClasses() may throw java.lang.IllegalAccessError, cannot access superclass...
// can't figure out why; probably classloader issue
for
(
Class
innerC
:
CUT
.
getDeclaredClasses
())
{
// non static inner classes and inherited inner classes are NOT targeted:
// NOTE: well, include them nonetheless...
// if (! Modifier.isStatic(innerC.getModifiers())) continue ;
// if (innerC.getDeclaringClass() != CUT) continue ;
// t3log.info("Found an inner static class " + innerC.getName());
g2s
.
addAll
(
mkG2worker
(
innerC
.
getName
(),
config
,
imap
,
loader
))
;
}
}
}
catch
(
Throwable
t
)
{
...
...
@@ -335,7 +383,7 @@ public class G2 {
return
;
}
if
(
g2s
.
length
>
1
)
{
String
s
=
"G2 will target
CUT and its internal
classes: "
;
String
s
=
"G2 will target
these
classes: "
;
for
(
int
k
=
0
;
k
<
g2s
.
length
;
k
++)
{
if
(
k
>
0
)
s
+=
", "
;
s
+=
g2s
[
k
].
g2sg
.
scope
.
CUT
.
getName
()
;
...
...
src/Sequenic/T3/DerivativeSuiteGens/Gen2/G2Config.java
View file @
85ebce29
package
Sequenic.T3.DerivativeSuiteGens.Gen2
;
import
java.io.Serializable
;
import
Sequenic.T3.Generator.Generator
;
import
Sequenic.T3.Sequence.Datatype.PARAM
;
public
class
G2Config
{
public
String
CUTrootDir
;
...
...
@@ -66,6 +71,14 @@ public class G2Config {
// controlling how violating sequences are shown:
public
boolean
showExcExecution
=
true
;
public
int
showLength
=
4
;
public
int
showDepth
=
5
;
public
int
showDepth
=
5
;
public
Generator
<
PARAM
,
Serializable
>
customPrimitivesGenerator
=
null
;
public
G2Config
usePrimitiveGenerator
(
Generator
<
PARAM
,
Serializable
>
gen
)
{
customPrimitivesGenerator
=
gen
;
return
this
;
}
}
src/Sequenic/T3/DerivativeSuiteGens/Gen2/G2SuiteGen.java
View file @
85ebce29
...
...
@@ -20,6 +20,7 @@ package Sequenic.T3.DerivativeSuiteGens.Gen2;
import
static
Sequenic
.
T3
.
Generator
.
GenCombinators
.
SequenceWhile
;
import
java.io.IOException
;
import
java.io.Serializable
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
...
...
@@ -82,13 +83,13 @@ public class G2SuiteGen {
public
float
fieldUpdateProbability
=
0.3f
;
private
G2SuiteGen
()
{}
//
private G2SuiteGen() {}
public
G2SuiteGen
(
String
CUTname
,
String
CUTrootDir
)
throws
Exception
{
this
(
CUTname
,
CUTrootDir
,
true
,
true
,
null
)
;
this
(
CUTname
,
CUTrootDir
,
true
,
true
,
null
,
null
)
;
}
/**
...
...
@@ -100,7 +101,9 @@ public class G2SuiteGen {
String
CUTrootDir
,
boolean
useCoverageGuidance
,
boolean
useStaticInfo
,
String
staticInfoDir
)
String
staticInfoDir
,
Generator
<
PARAM
,
Serializable
>
customPrimValGenerator
)
throws
Exception
{
//t3log.info("** CUT = " + CUT.getName());
...
...
@@ -137,31 +140,17 @@ public class G2SuiteGen {
}
}
configure
(
CUT
,
staticInfoDir
)
;
configure
(
CUT
,
staticInfoDir
,
customPrimValGenerator
)
;
}
// configuring other stuffs ; called from the constructor.
private
void
configure
(
Class
CUT
,
String
staticInfoDir
)
{
private
void
configure
(
Class
CUT
,
String
staticInfoDir
,
Generator
<
PARAM
,
Serializable
>
customPrimValGenerator
)
{
// Be careful with the order of setting up!
// setting up implementation-map and testing scope:
imap
=
new
ImplementationMap
(
new
String
[
0
])
;
scope
=
new
TestingScope
(
imap
,
CUT
)
;
// Forcefully adding private constructors to the scope... hackish.
scope
.
configureForADTtesting
()
;
if
(
true
/* scope.constructors.isEmpty() && scope.creatorMethods.isEmpty() */
)
{
for
(
Constructor
co
:
CUT
.
getDeclaredConstructors
())
{
int
mod
=
co
.
getModifiers
()
;
if
(
Modifier
.
isPrivate
(
mod
)
&&
!
Modifier
.
isAbstract
(
mod
))
{
scope
.
forceConstructors
.
add
(
co
)
;
}
}
if
(!
scope
.
forceConstructors
.
isEmpty
())
{
t3log
.
info
(
"Forcefully adding private constructors into the scope of "
+
CUT
.
getName
())
;
}
}
// read various static information provided in file(s):
if
(
staticInfoDir
!=
null
)
{
try
{
...
...
@@ -190,7 +179,7 @@ public class G2SuiteGen {
}
// setup value generator, and custom pool:
gen2vmg
=
new
G2ValueMG
(
imap
)
;
gen2vmg
=
new
G2ValueMG
(
imap
,
customPrimValGenerator
)
;
resetSeededConstants
()
;
pool
=
gen2vmg
.
pool
;
valueMG
=
gen2vmg
.
valueMG
()
;
...
...
@@ -484,10 +473,38 @@ public class G2SuiteGen {
*
* If maximum length is reached and we reach stagnation, we reset the legth
* to 1.
*
* If the testing scope does not contain any constructor/factory to create an instance of
* the SUT the method will however returns null.
*/
private
i
nt
refine
(
int
N
)
{
private
I
nt
eger
refine
(
int
N
)
{
// prepare the scope
scope
.
configureForADTtesting
();
// If we have no constructor nor creation method, forcefully add declared
// non-visible constructors:
if
(
scope
.
constructors
.
isEmpty
()
&&
scope
.
creatorMethods
().
isEmpty
())
{
boolean
added
=
false
;
for
(
Constructor
co
:
scope
.
CUT
.
getDeclaredConstructors
())
{
int
mod
=
co
.
getModifiers
()
;
if
(!
Modifier
.
isAbstract
(
mod
))
{
added
=
true
;
scope
.
constructors
.
add
(
co
)
;
}
}
if
(
added
)
{
Logger
.
getLogger
(
CONSTANTS
.
T3loggerName
).
info
(
"Forcefully adding non-visible constructors into the scope of "
+
scope
.
CUT
.
getName
())
;
}
else
{
// if forcing fails, then we simply have no means to create an instance of
// the CUT, hence also no means to produce prefixes ;
Logger
.
getLogger
(
CONSTANTS
.
T3loggerName
).
info
(
"Cannot find a constructor/factory to instantiate "
+
scope
.
CUT
.
getName
()
+
" to create prefixes. No prefixes will be generated."
)
;
return
null
;
}
}
if
(
staticInfo
!=
null
)
{
resetSeededConstants
()
;
addSeededSPrimitives
(
staticInfo
.
getAllConstansts
())
;
...
...
@@ -558,9 +575,12 @@ public class G2SuiteGen {
/**
* This will generate up to N prefixes iteratively. It returns the number
* of prefixes it manages to generate.
*
* If the testing scope does not contain any constructor/factory to create an instance of
* the SUT the method will however returns null.
*/
public
i
nt
incrementallyGeneratePrefixes
(
int
N
,
int
maxlength
,
int
maxdepth
)
{
System
.
err
.
println
(
">>> invoking incrementallyGeneratePrefixes..."
)
;
public
I
nt
eger
incrementallyGeneratePrefixes
(
int
N
,
int
maxlength
,
int
maxdepth
)
{
// t3log.info
(">>> invoking incrementallyGeneratePrefixes...") ;
if
(
currentPrefixes
==
null
)
{
currentPrefixes
=
new
Prefixes
(
maxlength
,
maxdepth
)
;
}
...
...
@@ -568,14 +588,16 @@ public class G2SuiteGen {
currentPrefixes
.
maxlength
=
maxlength
;
currentPrefixes
.
ObjStructureMaxDepth
=
maxdepth
;
}
int
added
=
currentPrefixes
.
refine
(
N
)
;
Integer
added
=
currentPrefixes
.
refine
(
N
)
;
if
(
added
==
null
)
{
return
null
;
}
if
(
added
==
0
)
{
System
.
err
.
println
(
">>> incrementallyGeneratePrefixes DONE;
FAIL to add any."
)
;
t3log
.
info
(
"
FAIL to add any
new prefix
."
)
;
}
else
{
System
.
err
.
println
(
">>> incrementallyGeneratePrefixes DONE. Adding "
+
added
+
" prefixes. New size: "
+
currentPrefixes
.
size
())
;
t3log
.
info
(
"Adding "
+
added
+
"; #prefixes now ="
+
currentPrefixes
.
size
())
;
}
return
added
;
}
...
...
src/Sequenic/T3/DerivativeSuiteGens/Gen2/G2ValueMG.java
View file @
85ebce29
...
...
@@ -27,6 +27,7 @@ import java.util.Map.Entry;
import
Sequenic.T3.ImplementationMap
;
import
Sequenic.T3.Pool
;
import
Sequenic.T3.T3Random
;
import
Sequenic.T3.Generator.GenCombinators
;
import
Sequenic.T3.Generator.Generator
;
import
Sequenic.T3.Generator.Value.*
;
import
Sequenic.T3.JavaType.JTfun
;
...
...
@@ -43,6 +44,12 @@ public class G2ValueMG {
public
G2Pool
pool
;
/**
* Two ways to provide custom control on generating primitive values. One is by supplying
* an explicit generator (below). And the other is by providing a list of constants.
*/
public
Generator
<
PARAM
,
Serializable
>
customPrimValGenerator
=
null
;
/**
* primitive values and strings that are seeded (more likely to be needed):
*/
...
...
@@ -122,7 +129,7 @@ public class G2ValueMG {
}
}
public
G2ValueMG
(
ImplementationMap
ImpsMap
)
{
public
G2ValueMG
(
ImplementationMap
ImpsMap
,
Generator
<
PARAM
,
Serializable
>
customPrimValGenerator
)
{
String
chars
=
"abcdefghijklmnopqrstuvwxyz"
;
chars
=
chars
+
chars
.
toUpperCase
()
...
...
@@ -137,6 +144,7 @@ public class G2ValueMG {
collectiongens
=
new
CollectionLikeMG
(
collectionSize
,
ImpsMap
)
;
lambdagens
=
new
LamdaMG
(
ImpsMap
)
;
refgens
=
new
REFMG
(
pool
)
;
this
.
customPrimValGenerator
=
customPrimValGenerator
;
}
/**
...
...
@@ -384,7 +392,17 @@ public class G2ValueMG {
}
else
{
toss
=
toss
-
chanceToPickPreviousPrimitive
;
if
(
toss
<
chanceToPickSeededPrimitive
)
o
=
getRandomSeededSPrimitive
(
ty
)
;
if
(
toss
<
chanceToPickSeededPrimitive
)
{
o
=
null
;
if
(
customPrimValGenerator
!=
null
)
{
if
(
rnd
.
nextFloat
()
<=
0.5
)
{
// 50% chance to pick using the custom generator
Maybe
<
Serializable
>
o_
=
customPrimValGenerator
.
generate
(
P
)
;
if
(
o_
!=
null
)
o
=
o_
.
val
;
}
}
if
(
o
==
null
)
o
=
getRandomSeededSPrimitive
(
ty
)
;
}
else
{
toss
=
toss
-
chanceToPickSeededPrimitive
;
if
(
toss
<
chanceToPickNeighbor
)
o
=
getRandomNeighbor
(
ty
)
;
...
...
@@ -436,7 +454,7 @@ public class G2ValueMG {
* This will construct the meta-generator to generate values.
*/
public
Generator
<
PARAM
,
STEP
>
valueMG
()
{
FUN
<
Generator
<
PARAM
,
STEP
>>
recGenerator
=
new
FUN
<
Generator
<
PARAM
,
STEP
>>()
;
Generator
<
PARAM
,
STEP
>
g
=
FirstOf
(
...
...
src/Sequenic/T3/DerivativeSuiteGens/Gen2/SingleTarget.java
View file @
85ebce29
...
...
@@ -124,13 +124,13 @@ public class SingleTarget {
if
(
target
instanceof
Method
)
{
Method
m
=
(
Method
)
target
;
if
(
isADT
)
{
g2sg
.
scope
.
configureForADTtesting
();
//
g2sg.scope.configureForADTtesting();
this will be done in the generate below