Commit 203c1647 authored by ISWB Prasetya's avatar ISWB Prasetya
Browse files

fixing issue that G2 cannot instantiate abstract/interface CUT

parent 45d6befd
......@@ -277,9 +277,9 @@ public class G2 {
Class CUT = loader.loadClass(CUTname) ;
if (CUT.isInterface() || Modifier.isAbstract(CUT.getModifiers())) {
// if CUT is an interface or abstract, find an implementation:
t3log.info(CUT.getName() + " is abstract or interface; trying to target a concrete implementation instead.");
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!");
......
......@@ -138,6 +138,9 @@ public class ObjectUnderTestMG {
} ;
}
// WP NOTE: don't think this will generate a constructor from a subclass...
// the call to the Solver below will only instantiate CUT's type variables,
// and won't look for for its subclass.
public Generator<SEQ_RT_info,STEP> useSubclassConstructor() {
return info -> {
//System.out.println("**>> info:" + info) ;
......@@ -148,6 +151,7 @@ public class ObjectUnderTestMG {
if (solution==null) return null ;
// if the solution is just the same as CUT, let it fail:
if (((JTfun) solution).fun == testingScope.CUT) return null ;
// WP NOTE: wonder if it will ever pass to this point....
PARAM p = new PARAM(null,solution) ;
Maybe<STEP> step = valueGenerator.generate(p) ;
if (step != null) {
......
......@@ -49,8 +49,18 @@ import Sequenic.T3.utils.SomeObject;
* of type C. Note that an abstract class can be publicly instantiable if it provides
* a concrete creation method.
*
* We will here maintain a map between classes that are not publicly instantiable, and their
* publicly instantiable implementations.
* We will here maintain a map between classes that are not publicly self-instantiable (in
* particular abstract classes and interfaces), and their publicly self-instantiable
* implementations.
*
* NOTE, TO DO: the class maintains two data structures for two purposes: (1) infomation on
* how to instantiate a set of classes, and (2) a certain kind of subclassing information
* -- see above. The logic of (1) is fully isolated here. (1) is used by value generators.
* (2) is used by the the class TestingScope, which then adds its own logic to infer how
* in instantiate CUT. The whole logic around (2) is used by target-obj generator to instantiate CUT.
*
* Having two logics for doing almost the same thing is ERROR PRONE and should be
* (TO DO) consolidated to a single logic.
*
*/
public class ImplementationMap {
......@@ -114,21 +124,36 @@ public class ImplementationMap {
Instantiation(Class C) { this.C = C ; }
public boolean hasKnownInstantiationMethod() {
return directConstructors.size() > 0 || indirectConstructors.size() > 0
public boolean hasKnownPublicInstantiationMethod() {
/*
System.err.println(">>>>> " + C.getName()
+ ", #dconstr=" + directConstructors.size()
+ ", #indirConstr=" + indirectConstructors.size()
+ ", #cretm=" + creationMethods.size()
+ ", #cretlikem=" + creationLikeMethods.size()
) ;
*/
return directConstructors.size() > 0 || indirectConstructors.size() > 0
|| creationMethods.size() > 0 || creationLikeMethods.size() > 0 ;
}
// true if C is not abstract nor interface, and has at least one public way
// to instantiate itself.
public boolean hasKnownPublicSelfInstantiationMethod() {
if (Modifier.isAbstract(C.getModifiers()) || C.isInterface()) return false ;
return directConstructors.size() > 0 || creationMethods.size() > 0 ;
}
void register(Constructor co) {
Class D = co.getDeclaringClass() ;
if (C == D) directConstructors.register(co) ;
if (C.isAssignableFrom(D)) indirectConstructors.register(co) ;
else if (C.isAssignableFrom(D)) indirectConstructors.register(co) ;
}
void register(Method m) {
Class D = m.getDeclaringClass() ;
if (C == D) creationMethods.register(m) ;
creationLikeMethods.register(m) ;
else creationLikeMethods.register(m) ;
}
Constructor getRndConstructor() {
......@@ -208,20 +233,26 @@ public class ImplementationMap {
knownClasses.put(C, instantiation) ;
// if C is an interface or abstract, add it to impsMap:
if (C.isInterface() || Modifier.isAbstract(C.getModifiers())) {
//if (C.isInterface() || Modifier.isAbstract(C.getModifiers())) {
// If C is not publicly self-instantiable:
if(!instantiation.hasKnownPublicSelfInstantiationMethod()) {
ConcurrentSet<Class> impsOfC = new ConcurrentSet<Class>() ;
for (Entry<Class,Instantiation> e : knownClasses.entrySet()) {
Class D = e.getKey() ;
Instantiation Di = e.getValue() ;
if (C != D && C.isAssignableFrom(D) && Di.hasKnownInstantiationMethod()) impsOfC.register(D) ;
// This is wrong logic:
//if (C != D && C.isAssignableFrom(D) && Di.hasKnownPublicInstantiationMethod()) impsOfC.register(D) ;
// Only add D if it is publicly self-instantiable:
if (C != D && C.isAssignableFrom(D) && Di.hasKnownPublicSelfInstantiationMethod()) impsOfC.register(D) ;
}
impsMap.put(C, impsOfC) ;
}
else {
// if C is concrete and instantiable, check if it can be added as an implementation to
// classes already in the impsMap:
if (instantiation.hasKnownInstantiationMethod()) {
for (Entry<Class,ConcurrentSet<Class>> e : impsMap.entrySet()) {
//if (instantiation.hasKnownPublicInstantiationMethod()) { <-- wrong!
if (instantiation.hasKnownPublicSelfInstantiationMethod()) {
for (Entry<Class,ConcurrentSet<Class>> e : impsMap.entrySet()) {
Class D = e.getKey() ;
if (C != D && D.isAssignableFrom(C)) e.getValue().register(C);
}
......@@ -278,26 +309,28 @@ public class ImplementationMap {
public boolean hasKnownInstantiationMethod(Class C) {
if (!knownClasses.containsKey(C)) registerClass(C) ;
return knownClasses.get(C).hasKnownInstantiationMethod() ;
return knownClasses.get(C).hasKnownPublicInstantiationMethod() ;
}
public int numberOfInstantiable() {
int k = 0 ;
for (Entry<Class,Instantiation> e : knownClasses.entrySet()) {
if (e.getValue().hasKnownInstantiationMethod()) k++ ;
if (e.getValue().hasKnownPublicInstantiationMethod()) k++ ;
}
return k ;
}
/**
* Get an implementation class of C. If C is already instantiable, return C itself. Else
* Get an implementation class of C. If C is already publicly self-instantiable, return C itself. Else
* we look in the impsMap. If no implementation map can be found, return null.
*/
public Class getRndImp(Class C) {
if (!knownClasses.containsKey(C)) registerClass(C) ;
Instantiation I = knownClasses.get(C) ;
if (I.hasKnownInstantiationMethod()) return C ;
//if (I.hasKnownPublicInstantiationMethod()) return C ; <-- wrong!
if (I.hasKnownPublicSelfInstantiationMethod()) return C ;
if (!impsMap.containsKey(C)) return null ;
//Logger.getLogger(CONSTANTS.T3loggerName).info("######## " + C.getName() + " has no known instantiation method!") ;
return impsMap.get(C).getRnd() ;
}
......@@ -311,7 +344,7 @@ public class ImplementationMap {
Instantiation I = e.getValue() ;
sb.append("\n " + D.getName()) ;
if (I.hasKnownInstantiationMethod())
if (I.hasKnownPublicInstantiationMethod())
sb.append(", instantiable dc/cm/ic/clm:"
+ I.directConstructors.size() + "/"
+ I.creationMethods.size() + "/"
......
......@@ -135,7 +135,7 @@ public class Solver {
JTfun solution2 = null ;
for (Entry<Class,ImplementationMap.Instantiation> e : imap.knownClasses.entrySet()) {
Class C = e.getKey() ;
if (! e.getValue().hasKnownInstantiationMethod()) continue ;
if (! e.getValue().hasKnownPublicInstantiationMethod()) continue ;
solution2 = new JTfun(C) ;
boolean found = true ;
for (JTfun B : ubounds) {
......
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