check lazy loading, classloader handling, loading & subtype constraints.
##
## Authors: Christian Thalinger
##
-## $Id: Makefile.am 6257 2006-12-28 13:43:06Z twisti $
+## $Id: Makefile.am 7433 2007-03-02 19:42:13Z edwin $
## Process this file with automake to produce Makefile.in
SUBDIRS = \
codepatching \
jasmin \
- native
+ native \
+ resolving
JAVA = $(top_builddir)/src/cacao/cacao
--- /dev/null
+SUBDIRS = \
+ classes1 \
+ classes2 \
+ classes3
+
+HARNESS_SOURCE_FILES = \
+ TestController.java \
+ TestLoader.java
+
+HARNESS_CLASS_FILES = \
+ TestController.class \
+ TestLoader.class
+
+TEST_SOURCE_FILES = \
+ test_instance_subtype_violated.java \
+ test_param_loading_constraint_violated_derived.java \
+ test_param_loading_constraint_violated.java \
+ test_param_subtype_violated.java \
+ test_retval_loading_constraint_violated.java \
+ test_simple_lazy_load.java
+
+TEST_NAMES = \
+ test_instance_subtype_violated \
+ test_param_loading_constraint_violated_derived \
+ test_param_loading_constraint_violated \
+ test_param_subtype_violated \
+ test_retval_loading_constraint_violated \
+ test_simple_lazy_load
+
+EXTRA_DIST = $(HARNESS_SOURCE_FILES) $(TEST_SOURCE_FILES)
+
+CLEANFILES = \
+ *.class
+
+JAVA = $(top_builddir)/src/cacao/cacao
+
+if WITH_CLASSPATH_GNU
+JAVAFLAGS = -Xbootclasspath:$(top_builddir)/src/lib/classes/:$(CLASSPATH_CLASSES)
+else
+JAVAFLAGS = -Xbootclasspath:$(CLASSPATH_CLASSES)
+endif
+
+check: $(HARNESS_CLASS_FILES)
+ for t in $(TEST_NAMES) ; do echo "TEST $$t" ; { $(JAVAC) $$t.java && $(JAVA) $$t ; } || exit 1 ; done
+
+$(HARNESS_CLASS_FILES): $(HARNESS_SOURCE_FILES)
+ $(JAVAC) $(HARNESS_SOURCE_FILES)
+
--- /dev/null
+import java.util.Vector;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestController {
+
+ boolean report_class_ids_ = false;
+ Vector expectations_ = new Vector();
+ boolean failed_ = false;
+
+ class Expectation {
+ String tag_;
+ String loader1_;
+ String loader2_;
+ String class_;
+
+ public Expectation(String tag, String ld1, String ld2, String cls) {
+ tag_ = tag;
+ loader1_ = ld1;
+ loader2_ = ld2;
+ class_ = cls;
+ }
+
+ public Expectation(String tag, String ld1, String cls) {
+ this(tag, ld1, null, cls);
+ }
+
+ public boolean matches(String tag, String ld1, String ld2, String cls) {
+ return tag_.equals(tag)
+ && loader1_.equals(ld1)
+ && ((loader2_ == ld2) || ((loader2_ != null) && (ld2 != null) && loader2_.equals(ld2)))
+ && class_.equals(cls);
+ }
+ }
+
+ public void setReportClassIDs(boolean rep) {
+ report_class_ids_ = rep;
+ }
+
+ void expect(Expectation exp) {
+ expectations_.add(exp);
+ }
+
+ void expect(String tag, String loader, String classname) {
+ expect(new Expectation(tag, loader, classname));
+ }
+
+ void expect(String tag, String loader1, String loader2, String classname) {
+ expect(new Expectation(tag, loader1, loader2, classname));
+ }
+
+ public void expect(String tag, ClassLoader loader, String classname) {
+ expect(tag, loaderName(loader), classname);
+ }
+
+ public void expect(String tag, ClassLoader loader1, ClassLoader loader2, String classname) {
+ expect(tag, loaderName(loader1), loaderName(loader2), classname);
+ }
+
+ public void expectLoadFromSystem(ClassLoader loader, String classname) {
+ expect("requested", loader, classname);
+ expect("delegated", loader, ClassLoader.getSystemClassLoader(), classname);
+ expect("loaded", loader, "<" + classname + ">");
+ }
+
+ public void expectDelegationAndDefinition(ClassLoader loader1, ClassLoader loader2, String classname) {
+ expect("requested", loader1, classname);
+ expect("delegated", loader1, loader2, classname);
+ expect("requested", loader2, classname);
+ expect("defined", loader2, "<" + classname + ">");
+ expect("loaded", loader1, "<" + classname + ">");
+ }
+
+ public void expectDelegationAndFound(ClassLoader loader1, ClassLoader loader2, String classname) {
+ expect("requested", loader1, classname);
+ expect("delegated", loader1, loader2, classname);
+ expect("requested", loader2, classname);
+ expect("found", loader2, "<" + classname + ">");
+ expect("loaded", loader1, "<" + classname + ">");
+ }
+
+ void fail(String message) {
+ log("FAIL: " + message);
+ failed_ = true;
+ }
+
+ void ok(String message) {
+ log("ok: " + message);
+ }
+
+ void fail(String message, String tag, String ld1, String ld2, String cls) {
+ fail(message + ": " + tag + " " + ld1 + " " + ld2 + " class=" + cls);
+ }
+
+ void ok(String tag, String ld1, String ld2, String cls) {
+ ok(tag + " " + ld1 + " " + ld2 + " class=" + cls);
+ }
+
+ public void expectEnd() {
+ if (expectations_.size() != 0)
+ fail("missing reports");
+ else
+ ok("got all expected reports");
+ }
+
+ public void checkStringGetter(Class cls, String methodname, String expected) {
+ String id = invokeStringGetter(cls, methodname);
+ if (id == null)
+ fail("could not get return value of " + methodname + "()");
+ else if (id.equals(expected))
+ ok("returned string matches: " + id);
+ else
+ fail("wrong string returned: " + id + ", expected: " + expected);
+ }
+
+ public void checkStringGetterMustFail(Class cls, String methodname) {
+ String id = invokeStringGetter(cls, methodname);
+ if (id == null)
+ ok("method invocation failed as expected: " + methodname + "()");
+ else
+ fail("method invocation did not fail as expected: " + methodname + "()");
+ }
+
+ public void checkClassId(Class cls, String expected) {
+ String id = getClassId(cls);
+ if (id == null)
+ fail("could not get class id");
+ else if (id.equals(expected))
+ ok("class id matches: " + id);
+ else
+ fail("wrong class id: " + id + ", expected: " + expected);
+ }
+
+ public synchronized void match(String tag, String ld1, String ld2, String cls) {
+ if (expectations_.size() == 0) {
+ fail("unexpected", tag, ld1, ld2, cls);
+ }
+ else {
+ Expectation exp = (Expectation) expectations_.firstElement();
+
+ if (exp.matches(tag, ld1, ld2, cls)) {
+ expectations_.remove(0);
+ ok(tag, ld1, ld2, cls);
+ }
+ else {
+ fail("unexpected", tag, ld1, ld2, cls);
+ }
+ }
+ }
+
+ void report(String tag, String loader, String classname) {
+ match(tag, loader, null, classname);
+ }
+
+ void report(String tag, String loader1, String loader2, String classname) {
+ match(tag, loader1, loader2, classname);
+ }
+
+ void report(String tag, ClassLoader loader, String classname) {
+ report(tag, loaderName(loader), classname);
+ }
+
+ void report(String tag, ClassLoader loader, Class cls) {
+ report(tag, loaderName(loader), className(cls));
+ }
+
+ void report(String tag, ClassLoader loader1, ClassLoader loader2, String classname) {
+ report(tag, loaderName(loader1), loaderName(loader2), classname);
+ }
+
+ public void reportRequest(ClassLoader loader, String classname) {
+ report("requested", loader, classname);
+ }
+
+ public void reportUnexpectedClassRequested(ClassLoader loader, String classname) {
+ report("unexpected class requested", loader, classname);
+ }
+
+ public void reportDelegation(ClassLoader loader, ClassLoader delegate, String classname) {
+ report("delegated", loaderName(loader), loaderName(delegate), classname);
+ }
+
+ public void reportDefinition(ClassLoader loader, Class cls) {
+ report("defined", loaderName(loader), className(cls));
+ }
+
+ public void reportFoundLoaded(ClassLoader loader, Class cls) {
+ report("found", loaderName(loader), className(cls));
+ }
+
+ public void reportLoaded(ClassLoader loader, Class cls) {
+ report("loaded", loaderName(loader), className(cls));
+ }
+
+ public void reportClassNotFound(ClassLoader loader, String classname, ClassNotFoundException e) {
+ report("class not found", loaderName(loader), classname);
+ }
+
+ public void reportException(Class cls, Throwable ex) {
+ report("exception", ex.getClass().getName(), className(cls));
+ log("exception was: " + ex);
+ // ex.printStackTrace(System.out);
+ }
+
+ public Class loadClass(ClassLoader loader, String classname) {
+ try {
+ Class cls = loader.loadClass(classname);
+
+ reportLoaded(loader, cls);
+
+ return cls;
+ }
+ catch (ClassNotFoundException e) {
+ reportClassNotFound(loader, classname, e);
+ }
+
+ return null;
+ }
+
+ public void log(String str) {
+ System.out.println(str);
+ }
+
+ public String loaderName(ClassLoader loader) {
+ if (loader == ClassLoader.getSystemClassLoader())
+ return "<SystemClassLoader>";
+
+ return (loader == null) ? "<null>" : loader.toString();
+ }
+
+ public String invokeStringGetter(Class cls, String methodname) {
+ try {
+ Method mid = cls.getMethod(methodname, null);
+
+ String id = (String) mid.invoke(null, null);
+
+ return id;
+ }
+ catch (NoSuchMethodException e) {
+ return null;
+ }
+ catch (InvocationTargetException e) {
+ reportException(cls, e.getCause());
+ return null;
+ }
+ catch (Exception e) {
+ reportException(cls, e);
+ return null;
+ }
+ }
+
+ public String getClassId(Class cls) {
+ return invokeStringGetter(cls, "id");
+ }
+
+ public String className(Class cls) {
+ if (report_class_ids_) {
+ String id = getClassId(cls);
+ if (id != null)
+ return "<" + cls.getName() + ":" + id + ">";
+ }
+
+ return "<" + cls.getName() + ">";
+ }
+
+ public void exit() {
+ expectEnd();
+ System.exit(failed_ ? 1 : 0);
+ }
+
+}
+
+// vim: et sw=4
--- /dev/null
+import java.util.Hashtable;
+import java.io.*;
+
+public class TestLoader extends ClassLoader {
+
+ Hashtable registry_;
+ String name_;
+ TestController controller_;
+
+ class Entry {
+ }
+
+ class ClassfileEntry extends Entry {
+ public String filename_;
+ public ClassfileEntry(String filename) { filename_ = filename; }
+ }
+
+ class DelegationEntry extends Entry {
+ public ClassLoader loader_;
+ public DelegationEntry(ClassLoader loader) { loader_ = loader; }
+ }
+
+ class SuperDelegationEntry extends Entry {
+ }
+
+ public TestLoader(ClassLoader parent, String name, TestController controller) {
+ super(parent);
+ name_ = name;
+ controller_ = controller;
+ registry_ = new Hashtable();
+ }
+
+ public void addClassfile(String classname, String filename) {
+ registry_.put(classname, new ClassfileEntry(filename));
+ }
+
+ public void addDelegation(String classname, ClassLoader loader) {
+ registry_.put(classname, new DelegationEntry(loader));
+ }
+
+ public void addParentDelegation(String classname) {
+ registry_.put(classname, new DelegationEntry(getParent()));
+ }
+
+ public void addSuperDelegation(String classname) {
+ registry_.put(classname, new SuperDelegationEntry());
+ }
+
+ public String toString() {
+ return "TestLoader<" + name_ + ">";
+ }
+
+ public Class loadClass(String classname) throws ClassNotFoundException {
+ controller_.reportRequest(this, classname);
+
+ Entry entry = (Entry) registry_.get(classname);
+
+ if (entry == null) {
+ controller_.reportUnexpectedClassRequested(this, classname);
+ throw new ClassNotFoundException(this + " does not know how to load class " + classname);
+ }
+
+ if (entry instanceof ClassfileEntry) {
+ Class cls = findLoadedClass(classname);
+
+ if (cls != null) {
+ controller_.reportFoundLoaded(this, cls);
+ return cls;
+ }
+
+ String filename = ((ClassfileEntry)entry).filename_;
+
+ try {
+ byte[] bytes = slurpFile(filename);
+
+ cls = defineClass(classname, bytes, 0, bytes.length);
+
+ controller_.reportDefinition(this, cls);
+
+ return cls;
+ }
+ catch (Exception e) {
+ throw new ClassNotFoundException(e.toString());
+ }
+ }
+ else if (entry instanceof DelegationEntry) {
+ ClassLoader delegate = ((DelegationEntry)entry).loader_;
+
+ controller_.reportDelegation(this, delegate, classname);
+
+ Class cls = delegate.loadClass(classname);
+
+ controller_.reportLoaded(this, cls);
+
+ return cls;
+ }
+
+ throw new ClassNotFoundException("unknown TestLoader entry: " + entry);
+ }
+
+ byte[] slurpFile(String filename) throws IOException {
+ File file = new File(filename);
+ InputStream is = new FileInputStream(file);
+ long len = file.length();
+ if (len > Integer.MAX_VALUE)
+ throw new IOException("file " + file.getName() + " is too large");
+ byte[] bytes = new byte[(int) len];
+
+ int ofs = 0;
+ int read = 0;
+ while ((ofs < len) && (read = is.read(bytes, ofs, bytes.length - ofs)) >= 0)
+ ofs += read;
+
+ if (ofs < len)
+ throw new IOException("error reading file " + file.getName());
+
+ is.close();
+ return bytes;
+ }
+}
+
+// vim: et sw=4
+
--- /dev/null
+public class BarPassFoo {
+ public static String id() {
+ return "classes1/BarPassFoo";
+ }
+
+ public Foo createFoo() {
+ return null;
+ }
+}
+
+// vim: et sw=4
--- /dev/null
+public class BarUseFoo {
+ public static String id() {
+ return "classes1/BarUseFoo";
+ }
+
+ public static String idOfFoo() {
+ return Foo.id();
+ }
+
+ public String useFoo(Foo foo) {
+ return foo.virtualId();
+ }
+
+ public static String useReturnedFoo() {
+ BarPassFoo bpf = new BarPassFoo();
+ Foo foo = bpf.createFoo();
+ return foo.virtualId();
+ }
+}
+
+// vim: et sw=4
+
--- /dev/null
+public class Foo {
+ public static String id() {
+ return "classes1/Foo";
+ }
+
+ public String virtualId() {
+ return id();
+ }
+}
+
+// vim: et sw=4
--- /dev/null
+SOURCE_FILES = \
+ BarPassFoo.java \
+ BarUseFoo.java \
+ Foo.java
+
+CLASS_FILES = \
+ BarPassFoo.class \
+ BarUseFoo.class \
+ Foo.class
+
+EXTRA_DIST = $(SOURCE_FILES)
+
+CLEANFILES = \
+ *.class
+
+check: $(CLASS_FILES)
+
+$(CLASS_FILES): $(SOURCE_FILES)
+ $(JAVAC) $(SOURCE_FILES)
+
--- /dev/null
+public class BarPassFoo {
+ public static String id() {
+ return "classes2/BarPassFoo";
+ }
+
+ public static String passit() {
+ Foo foo = new Foo();
+ BarUseFoo bar = new BarUseFoo();
+
+ return bar.useFoo(foo);
+ }
+
+ public static String passDerivedFoo() {
+ DerivedFoo dfoo = new DerivedFoo();
+ BarUseFoo bar = new BarUseFoo();
+
+ return bar.useFoo(dfoo);
+ }
+
+ public static String passDerivedFooInstance() {
+ Foo foo = new DerivedFoo();
+
+ return foo.virtualId();
+ }
+
+ public Foo createFoo() {
+ return new Foo();
+ }
+}
+
+// vim: et sw=4
--- /dev/null
+public class BarUseFoo {
+ public static String id() {
+ return "classes2/BarUseFoo";
+ }
+
+ public static String idOfFoo() {
+ return Foo.id();
+ }
+
+ public String useFoo(Foo foo) {
+ return "not implemented";
+ }
+}
+
+// vim: et sw=4
+
--- /dev/null
+public class DerivedFoo extends Foo {
+ public static String id() {
+ return "classes2/DerivedFoo";
+ }
+}
+
+// vim: et sw=4
--- /dev/null
+public class Foo {
+ public static String id() {
+ return "classes2/Foo";
+ }
+
+ public String virtualId() {
+ return id();
+ }
+}
+
+// vim: et sw=4
--- /dev/null
+SOURCE_FILES = \
+ BarPassFoo.java \
+ BarUseFoo.java \
+ DerivedFoo.java \
+ Foo.java
+
+CLASS_FILES = \
+ BarPassFoo.class \
+ BarUseFoo.class \
+ DerivedFoo.class \
+ Foo.class
+
+EXTRA_DIST = $(SOURCE_FILES)
+
+CLEANFILES = \
+ *.class
+
+check: $(CLASS_FILES)
+
+$(CLASS_FILES): $(SOURCE_FILES)
+ $(JAVAC) $(SOURCE_FILES)
+
+
--- /dev/null
+public class BarPassFoo {
+ public static String id() {
+ return "classes3/BarPassFoo";
+ }
+
+ public static String passit() {
+ Foo foo = new Foo();
+ BarUseFoo bar = new BarUseFoo();
+
+ return bar.useFoo(foo);
+ }
+
+ public static String passDerivedFoo() {
+ DerivedFoo dfoo = new DerivedFoo();
+ BarUseFoo bar = new BarUseFoo();
+
+ return bar.useFoo(dfoo);
+ }
+}
+
+// vim: et sw=4
--- /dev/null
+public class BarUseFoo {
+ public static String id() {
+ return "classes3/BarUseFoo";
+ }
+
+ public static String idOfFoo() {
+ return Foo.id();
+ }
+
+ public String useFoo(Foo foo) {
+ return "not implemented";
+ }
+}
+
+// vim: et sw=4
+
--- /dev/null
+public class DerivedFoo extends Foo {
+ public static String id() {
+ return "classes3/DerivedFoo";
+ }
+}
+
+// vim: et sw=4
--- /dev/null
+public class Foo {
+ public static String id() {
+ return "classes3/Foo";
+ }
+
+ public String virtualId() {
+ return "not implemented";
+ }
+}
+
+// vim: et sw=4
--- /dev/null
+SOURCE_FILES = \
+ BarPassFoo.java \
+ BarUseFoo.java \
+ DerivedFoo.java \
+ Foo.java
+
+CLASS_FILES = \
+ BarPassFoo.class \
+ BarUseFoo.class \
+ DerivedFoo.class \
+ Foo.class
+
+EXTRA_DIST = $(SOURCE_FILES)
+
+CLEANFILES = \
+ *.class
+
+check: $(CLASS_FILES)
+
+$(CLASS_FILES): $(SOURCE_FILES)
+ $(JAVAC) $(SOURCE_FILES)
+
+
--- /dev/null
+public class test_instance_subtype_violated {
+
+ public static void main(String[] args) {
+ TestController ct = new TestController();
+
+ TestLoader ld1 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld1", ct);
+ TestLoader ld2 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld2", ct);
+ TestLoader ld3 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld3", ct);
+
+ ld1.addClassfile("BarUseFoo", "classes1/BarUseFoo.class");
+ ld1.addClassfile("Foo", "classes1/Foo.class");
+ ld1.addParentDelegation("java.lang.Object");
+ ld1.addParentDelegation("java.lang.String");
+
+ ld2.addClassfile("BarPassFoo", "classes2/BarPassFoo.class");
+ ld2.addDelegation("BarUseFoo", ld1);
+ ld2.addDelegation("Foo", ld1);
+ ld2.addDelegation("DerivedFoo", ld3);
+ ld2.addParentDelegation("java.lang.Object");
+ ld2.addParentDelegation("java.lang.String");
+
+ ld3.addClassfile("Foo", "classes3/Foo.class");
+ ld3.addClassfile("DerivedFoo", "classes3/DerivedFoo.class");
+ ld3.addParentDelegation("java.lang.Object");
+ ld3.addParentDelegation("java.lang.String");
+
+
+ // loading BarPassFoo
+ ct.expect("requested", ld2, "BarPassFoo");
+ ct.expect("defined", ld2, "<BarPassFoo>");
+ ct.expect("loaded", ld2, "<BarPassFoo>");
+
+ Class cls = ct.loadClass(ld2, "BarPassFoo");
+
+ // linking BarPassFoo
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
+
+ // executing BarPassFoo.passDerivedFooInstance: new DerivedFoo
+ ct.expectDelegationAndDefinition(ld2, ld3, "DerivedFoo");
+
+ // linking (ld3, DerivedFoo)
+ ct.expect("requested", ld3, "Foo");
+ ct.expect("defined", ld3, "<Foo>");
+ ct.expectLoadFromSystem(ld3, "java.lang.Object");
+
+ // resolving Foo.virtualId
+ // the deferred subtype check ((ld2, DerivedFoo) subtypeof (ld2, Foo)) is done
+ ct.expectDelegationAndDefinition(ld2, ld1, "Foo");
+ // ...linking (ld2, Foo) == (ld1, Foo)
+ ct.expectLoadFromSystem(ld1, "java.lang.Object");
+
+ // the subtype constraint ((ld2, DerivedFoo) subtypeof (ld2, Foo)) is violated
+ ct.expect("exception", "java.lang.LinkageError", "<BarPassFoo>");
+
+ ct.checkStringGetterMustFail(cls, "passDerivedFooInstance");
+
+ ct.exit();
+ }
+
+}
+
+// vim: et sw=4
--- /dev/null
+public class test_param_loading_constraint_violated {
+
+ public static void main(String[] args) {
+ TestController ct = new TestController();
+
+ TestLoader ld1 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld1", ct);
+ TestLoader ld2 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld2", ct);
+
+ ld1.addClassfile("BarUseFoo", "classes1/BarUseFoo.class");
+ ld1.addClassfile("Foo", "classes1/Foo.class");
+ ld1.addParentDelegation("java.lang.Object");
+ ld1.addParentDelegation("java.lang.String");
+
+ ld2.addClassfile("BarPassFoo", "classes2/BarPassFoo.class");
+ ld2.addClassfile("Foo", "classes2/Foo.class");
+ ld2.addDelegation("BarUseFoo", ld1);
+ ld2.addParentDelegation("java.lang.Object");
+ ld2.addParentDelegation("java.lang.String");
+
+
+ // loading BarPassFoo
+ ct.expect("requested", ld2, "BarPassFoo");
+ ct.expect("defined", ld2, "<BarPassFoo>");
+ ct.expect("loaded", ld2, "<BarPassFoo>");
+
+ Class cls = ct.loadClass(ld2, "BarPassFoo");
+
+ // linking BarPassFoo
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
+
+ // executing BarPassFoo.passit: new Foo
+ ct.expect("requested", ld2, "Foo");
+ ct.expect("defined", ld2, "<Foo>");
+
+ // executing BarPassFoo.passit: new BarUseFoo
+ ct.expectDelegationAndDefinition(ld2, ld1, "BarUseFoo");
+ // ...linking BarUseFoo
+ ct.expectLoadFromSystem(ld1, "java.lang.Object");
+
+ // resolving Foo.virtualId() from BarUseFoo
+ ct.expect("requested", ld1, "Foo");
+
+ // the loading constraing (ld1,ld2,Foo) is violated
+ ct.expect("exception", "java.lang.LinkageError", "<BarPassFoo>");
+
+ ct.checkStringGetterMustFail(cls, "passit");
+
+ ct.exit();
+ }
+
+}
+
+// vim: et sw=4
--- /dev/null
+public class test_param_loading_constraint_violated_derived {
+
+ public static void main(String[] args) {
+ TestController ct = new TestController();
+
+ TestLoader ld1 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld1", ct);
+ TestLoader ld2 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld2", ct);
+ TestLoader ld3 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld3", ct);
+
+ ld1.addClassfile("BarUseFoo", "classes1/BarUseFoo.class");
+ ld1.addClassfile("Foo", "classes1/Foo.class");
+ ld1.addParentDelegation("java.lang.Object");
+ ld1.addParentDelegation("java.lang.String");
+
+ ld2.addClassfile("BarPassFoo", "classes2/BarPassFoo.class");
+ ld2.addDelegation("BarUseFoo", ld1);
+ ld2.addDelegation("Foo", ld3);
+ ld2.addDelegation("DerivedFoo", ld3);
+ ld2.addParentDelegation("java.lang.Object");
+ ld2.addParentDelegation("java.lang.String");
+
+ ld3.addClassfile("Foo", "classes3/Foo.class");
+ ld3.addClassfile("DerivedFoo", "classes3/DerivedFoo.class");
+ ld3.addParentDelegation("java.lang.Object");
+ ld3.addParentDelegation("java.lang.String");
+
+
+ // loading BarPassFoo
+ ct.expect("requested", ld2, "BarPassFoo");
+ ct.expect("defined", ld2, "<BarPassFoo>");
+ ct.expect("loaded", ld2, "<BarPassFoo>");
+
+ Class cls = ct.loadClass(ld2, "BarPassFoo");
+
+ // linking BarPassFoo
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
+
+ // executing BarPassFoo.passDerivedFoo: new DerivedFoo
+ ct.expectDelegationAndDefinition(ld2, ld3, "DerivedFoo");
+
+ // linking (ld3, DerivedFoo)
+ ct.expect("requested", ld3, "Foo");
+ ct.expect("defined", ld3, "<Foo>");
+ ct.expectLoadFromSystem(ld3, "java.lang.Object");
+
+ // executing BarPassFoo.passit: new BarUseFoo
+ ct.expectDelegationAndDefinition(ld2, ld1, "BarUseFoo");
+
+ // linking BarUseFoo
+ ct.expectLoadFromSystem(ld1, "java.lang.Object");
+
+ // resolving BarUseFoo.useFoo
+ // the deferred subtype check ((ld2, DerivedFoo) subtypeof (ld2, Foo)) is done
+ ct.expectDelegationAndFound(ld2, ld3, "Foo");
+
+ // resolving Foo.virtualId() from BarUseFoo
+ ct.expect("requested", ld1, "Foo");
+
+ // the loading constraint (ld1,ld2,Foo) is violated
+ ct.expect("exception", "java.lang.LinkageError", "<BarPassFoo>");
+
+ ct.checkStringGetterMustFail(cls, "passDerivedFoo");
+
+ ct.exit();
+ }
+
+}
+
+// vim: et sw=4
--- /dev/null
+public class test_param_subtype_violated {
+
+ public static void main(String[] args) {
+ TestController ct = new TestController();
+
+ TestLoader ld1 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld1", ct);
+ TestLoader ld2 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld2", ct);
+ TestLoader ld3 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld3", ct);
+
+ ld1.addClassfile("BarUseFoo", "classes1/BarUseFoo.class");
+ ld1.addClassfile("Foo", "classes1/Foo.class");
+ ld1.addParentDelegation("java.lang.Object");
+ ld1.addParentDelegation("java.lang.String");
+
+ ld2.addClassfile("BarPassFoo", "classes2/BarPassFoo.class");
+ ld2.addDelegation("BarUseFoo", ld1);
+ ld2.addDelegation("Foo", ld1);
+ ld2.addDelegation("DerivedFoo", ld3);
+ ld2.addParentDelegation("java.lang.Object");
+ ld2.addParentDelegation("java.lang.String");
+
+ ld3.addClassfile("Foo", "classes3/Foo.class");
+ ld3.addClassfile("DerivedFoo", "classes3/DerivedFoo.class");
+ ld3.addParentDelegation("java.lang.Object");
+ ld3.addParentDelegation("java.lang.String");
+
+
+ // loading BarPassFoo
+ ct.expect("requested", ld2, "BarPassFoo");
+ ct.expect("defined", ld2, "<BarPassFoo>");
+ ct.expect("loaded", ld2, "<BarPassFoo>");
+
+ Class cls = ct.loadClass(ld2, "BarPassFoo");
+
+ // linking BarPassFoo
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
+
+ // executing BarPassFoo.passDerivedFoo: new DerivedFoo
+ ct.expectDelegationAndDefinition(ld2, ld3, "DerivedFoo");
+ // ...linking (ld3, DerivedFoo)
+ ct.expect("requested", ld3, "Foo");
+ ct.expect("defined", ld3, "<Foo>");
+ ct.expectLoadFromSystem(ld3, "java.lang.Object");
+
+ // executing BarPassFoo.passDerivedFoo: new BarUseFoo
+ ct.expectDelegationAndDefinition(ld2, ld1, "BarUseFoo");
+ // ...linking BarUseFoo
+ ct.expectLoadFromSystem(ld1, "java.lang.Object");
+
+ // resolving BarUseFoo.useFoo
+ // the deferred subtype check ((ld2, DerivedFoo) subtypeof (ld2, Foo)) is done
+ ct.expectDelegationAndDefinition(ld2, ld1, "Foo");
+
+ // the subtype constraint ((ld2, DerivedFoo) subtypeof (ld2, Foo)) is violated
+ ct.expect("exception", "java.lang.LinkageError", "<BarPassFoo>");
+
+ ct.checkStringGetterMustFail(cls, "passDerivedFoo");
+
+ ct.exit();
+ }
+
+}
+
+// vim: et sw=4
--- /dev/null
+public class test_retval_loading_constraint_violated {
+
+ public static void main(String[] args) {
+ TestController ct = new TestController();
+
+ TestLoader ld1 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld1", ct);
+ TestLoader ld2 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld2", ct);
+
+ ld1.addClassfile("BarUseFoo", "classes1/BarUseFoo.class");
+ ld1.addClassfile("Foo", "classes1/Foo.class");
+ ld1.addDelegation("BarPassFoo", ld2);
+ ld1.addParentDelegation("java.lang.Object");
+ ld1.addParentDelegation("java.lang.String");
+
+ ld2.addClassfile("BarPassFoo", "classes2/BarPassFoo.class");
+ ld2.addClassfile("Foo", "classes2/Foo.class");
+ ld2.addParentDelegation("java.lang.Object");
+ ld2.addParentDelegation("java.lang.String");
+
+
+ // loading BarUseFoo
+ ct.expect("requested", ld1, "BarUseFoo");
+ ct.expect("defined", ld1, "<BarUseFoo>");
+ ct.expect("loaded", ld1, "<BarUseFoo>");
+
+ Class cls = ct.loadClass(ld1, "BarUseFoo");
+
+ // linking BarUseFoo
+ ct.expectLoadFromSystem(ld1, "java.lang.Object");
+
+ // executing BarUseFoo.useReturnedFoo: new BarPassFoo
+ ct.expectDelegationAndDefinition(ld1, ld2, "BarPassFoo");
+ // ...linking BarPassFoo
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
+
+ // resolving BarPassFoo.createFoo
+ ct.expect("requested", ld2, "Foo");
+ ct.expect("defined", ld2, "<Foo>");
+ ct.expect("requested", ld1, "Foo");
+ // ...the loading constraing (ld1,ld2,Foo) is violated
+ ct.expect("exception", "java.lang.LinkageError", "<BarUseFoo>");
+
+ ct.checkStringGetterMustFail(cls, "useReturnedFoo");
+
+ ct.exit();
+ }
+
+}
+
+// vim: et sw=4
--- /dev/null
+public class test_simple_lazy_load {
+
+ public static void main(String[] args) {
+ TestController ct = new TestController();
+
+ TestLoader ld1 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld1", ct);
+
+ ld1.addClassfile("BarUseFoo", "classes1/BarUseFoo.class");
+ ct.expect("requested", ld1, "BarUseFoo");
+ ct.expect("defined", ld1, "<BarUseFoo>");
+ ct.expect("loaded", ld1, "<BarUseFoo>");
+ Class cls = ct.loadClass(ld1, "BarUseFoo");
+ ct.expectEnd();
+
+ ld1.addParentDelegation("java.lang.Object");
+ ct.expectLoadFromSystem(ld1, "java.lang.Object");
+ ct.checkClassId(cls, "classes1/BarUseFoo");
+ ct.expectEnd();
+
+ ld1.addClassfile("Foo", "classes1/Foo.class");
+ ct.setReportClassIDs(true);
+ ct.expect("requested", ld1, "Foo");
+ ct.expect("defined", ld1, "<Foo:classes1/Foo>");
+ ct.checkStringGetter(cls, "idOfFoo", "classes1/Foo");
+ ct.expectEnd();
+
+ ct.exit();
+ }
+
+}
+
+// vim: et sw=4