experiments/JavaClassReloaderTests.st
branchdevelopment
changeset 2730 272689c14005
child 2756 6659925a80a4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/experiments/JavaClassReloaderTests.st	Sun Sep 15 01:02:01 2013 +0100
@@ -0,0 +1,402 @@
+"
+ Copyright (c) 2010-2011 Jan Vrany, Jan Kurs & Marcel Hlopko,
+                         SWING Research Group, Czech Technical University 
+                         in Prague
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the 'Software'), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+"
+"{ Package: 'stx:libjava/experiments' }"
+
+TestCase subclass:#JavaClassReloaderTests
+	instanceVariableNames:'testClassLoader'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Languages-Java-Tests-ClassReloading'
+!
+
+!JavaClassReloaderTests class methodsFor:'documentation'!
+
+copyright
+"
+ Copyright (c) 2010-2011 Jan Vrany, Jan Kurs & Marcel Hlopko,
+                         SWING Research Group, Czech Technical University 
+                         in Prague
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the 'Software'), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+
+"
+!
+
+history
+
+    "Created: #resources / 21-12-2012 / 18:09:27 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+! !
+
+!JavaClassReloaderTests class methodsFor:'resources'!
+
+resources
+
+  ^ Array 
+        with: JavaInitializedResource.
+
+    "Created: / 21-12-2012 / 18:09:27 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+! !
+
+!JavaClassReloaderTests methodsFor:'private'!
+
+compile: sourceCode
+    | classes |
+
+    classes := JavaCompiler compile: sourceCode.
+"/    classes do:[:cls|cls classLoader: testClassLoader] .
+    ^classes
+
+    "Created: / 16-12-2012 / 17:02:41 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+    "Modified: / 09-04-2013 / 22:39:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+compileAndRegister: sourceCode
+    |compiledClasses|
+
+    compiledClasses := self compile: sourceCode.
+    ^ self register: compiledClasses.
+
+    "Created: / 16-12-2012 / 16:59:19 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+!
+
+performTest
+
+    JavaClassReader classLoaderQuerySignal answer: testClassLoader do:[
+        super performTest
+    ].
+
+    "Created: / 16-12-2012 / 16:35:01 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+!
+
+register: aClassOrArray
+
+    ^aClassOrArray isArray ifTrue:[
+        JavaVM registry registerClasses: aClassOrArray .
+        JavaVM registry classNamed: aClassOrArray anElement name loader: aClassOrArray anElement classLoader
+    ] ifFalse:[
+        JavaVM registry registerClass: aClassOrArray.
+        JavaVM registry classNamed: aClassOrArray name loader: aClassOrArray classLoader
+    ].
+
+    "Created: / 16-12-2012 / 17:02:04 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+    "Modified: / 09-04-2013 / 22:27:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+testInfrastructure
+
+    |compiledClass|
+
+    self assert: (JavaClassReader classLoaderQuerySignal query = testClassLoader ) 
+        message: 'tests should run in testClassLoader sandbox'.
+    compiledClass := self compileAndRegister: '
+public class HelloSun {
+
+    public String hello() {
+        return "helloooo";
+    }
+
+}
+'.
+    self assert: compiledClass notNil message: 'Java compiler should be working for these tests to run'.
+    self assert: compiledClass classLoader = testClassLoader message: 'compiled classes should have testClassLoader as their defining cl'.
+    self assert: (JavaVM registry getClassesDefinedBy: testClassLoader) size = 1 message: 'only classes from these tests should use testClassLoader'.
+    self assert: (JavaVM registry getClassesDefinedBy: testClassLoader) anElement == compiledClass message: 'compiled classes should be registered in testClassLoader'.
+
+    "Created: / 16-12-2012 / 16:38:17 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+! !
+
+!JavaClassReloaderTests methodsFor:'running'!
+
+setUp
+    testClassLoader := JAVA java lang ClassLoader new.
+
+    "Created: / 16-12-2012 / 16:32:32 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+!
+
+tearDown
+    JavaVM registry unregisterClassLoader: testClassLoader.
+
+    "Created: / 16-12-2012 / 16:33:31 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+! !
+
+!JavaClassReloaderTests methodsFor:'test helpers'!
+
+callerClass
+    | callerClass |
+    callerClass := (JavaCompiler 
+            compile: '
+package classReloadingTests;
+public class Caller {
+    public String callFooToString(Object c) {
+        return c.toString();
+    }   
+}
+') anElement.
+    callerClass 
+        ifNil: [ self error: 'callerClass is expected to be not nil in these tests' ].
+    ^ callerClass.
+
+    "Created: / 06-12-2012 / 21:41:35 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+    "Modified: / 18-12-2012 / 14:00:12 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+    "Modified: / 04-01-2013 / 14:51:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+compileAndRegisterChangingClassParent
+
+    self compileAndRegister: '
+package classReloadingTests;
+public class ChangingClassParent {
+    public String foo() {
+        return "parent";
+    }
+
+    public String toString() {
+        return "" + foo();
+    }   
+}'.
+
+    "Created: / 18-12-2012 / 13:47:32 / Marcel Hlopko <marcel.hlopko@fit.cvut.cz>"
+! !
+
+!JavaClassReloaderTests methodsFor:'tests - unloading'!
+
+test_unloading_01
+    "
+    1) compile class A1 and class A2 inheriting from A1 
+    2) compile class B that instantiates A and  call its method A2.bar from B.foo
+    3) remove class A1 (should remove A2 as well)
+    4) call B.foo and checks it raises ClassNotFoundException
+    5) compile class A2
+    6) call B.foo and checks it returns new value
+    "
+
+    | jclassA1 jclassA2 jclassB jinstB |
+
+    jclassA1 := self compileAndRegister:'
+public class test_unloading_01_A1 { 
+    public int bar() {
+        return 1;
+    }
+}'.
+
+    jclassA2 := self compileAndRegister:'
+public class test_unloading_01_A2 extends test_unloading_01_A1 { 
+}'.
+
+
+    jclassB := self compileAndRegister:'
+public class test_unloading_01_B { 
+    public int foo() {
+        return (new test_unloading_01_A2()).bar();
+    }
+}'.
+    jinstB := jclassB new.
+    self assert: jinstB foo == 1.
+    self assert: (Smalltalk allClasses includesIdentical: jclassA1).
+    self assert: (Smalltalk allClasses includesIdentical: jclassA2).
+
+
+    jclassA1 removeFromSystem.
+    self assert: (Smalltalk allClasses includesIdentical: jclassA1) not.
+    self assert: (Smalltalk allClasses includesIdentical: jclassA2) not.
+
+    [
+        jinstB foo.
+        self assert: false "/ should raise ClassNotFoundException
+    ] on: JAVA java lang ClassNotFoundException do:[
+        self assert: true.
+    ].
+
+    jclassA2 := self compileAndRegister:'
+public class test_unloading_01_A2 { 
+    public int bar() {
+        return 20;
+    }
+}'.
+
+    self assert: jinstB foo == 20.
+
+    "Created: / 14-09-2013 / 18:57:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_unloading_02a
+    "
+    1) compile interface I1 and class A2 implementing I1
+    2) compile class B that instantiates A and  call its method A2.bar from B.foo
+    3) remove class I1 (should remove A2 as well)
+    4) call B.foo and checks it raises ClassNotFoundException
+    5) compile class A2
+    6) call B.foo and checks it returns new value
+    "
+
+    | jclassI1 jclassA2 jclassB jinstB |
+
+    jclassI1 := self compileAndRegister:'
+public interface test_unloading_01_I1 { 
+    public int bar()
+}'.
+
+    jclassA2 := self compileAndRegister:'
+public class test_unloading_01_A2 implements test_unloading_01_I1 { 
+    public int bar() { return 1; }
+}'.
+
+
+    jclassB := self compileAndRegister:'
+public class test_unloading_01_B { 
+    public int foo() {
+        return (new test_unloading_01_A2()).bar();
+    }
+}'.
+    jinstB := jclassB new.
+    self assert: jinstB foo == 1.
+    self assert: (Smalltalk allClasses includesIdentical: jclassI1).
+    self assert: (Smalltalk allClasses includesIdentical: jclassA2).
+
+
+    jclassI1 removeFromSystem.
+    self assert: (Smalltalk allClasses includesIdentical: jclassI1) not.
+    self assert: (Smalltalk allClasses includesIdentical: jclassA2) not.
+
+    [
+        jinstB foo.
+        self assert: false "/ should raise ClassNotFoundException
+    ] on: JAVA java lang ClassNotFoundException do:[
+        self assert: true.
+    ].
+
+    jclassA2 := self compileAndRegister:'
+public class test_unloading_01_A2 { 
+    public int bar() {
+        return 20;
+    }
+}'.
+
+    self assert: jinstB foo == 20.
+
+    "Created: / 14-09-2013 / 19:02:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_unloading_02b
+    "
+    1) compile interface I1, I2, I2 implenting I1, and class A2 implementing I2
+    2) compile class B that instantiates A and  call its method A2.bar from B.foo
+    3) remove class I1 (should remove A2 as well)
+    4) call B.foo and checks it raises ClassNotFoundException
+    5) compile class A2
+    6) call B.foo and checks it returns new value
+    "
+
+    | jclassI1 jclassI2 jclassA2 jclassB jinstB |
+
+    jclassI1 := self compileAndRegister:'
+public interface test_unloading_01_I1 { 
+    public int bar()
+}'.
+
+    jclassI2 := self compileAndRegister:'
+public interface test_unloading_01_I2 extends  test_unloading_01_I1 { 
+}'.
+
+
+    jclassA2 := self compileAndRegister:'
+public class test_unloading_01_A2 implements test_unloading_01_I1 { 
+    public int bar() { return 1; }
+}'.
+
+
+    jclassB := self compileAndRegister:'
+public class test_unloading_01_B { 
+    public int foo() {
+        return (new test_unloading_01_A2()).bar();
+    }
+}'.
+    jinstB := jclassB new.
+    self assert: jinstB foo == 1.
+    self assert: (Smalltalk allClasses includesIdentical: jclassI1).
+    self assert: (Smalltalk allClasses includesIdentical: jclassA2).
+
+
+    jclassI1 removeFromSystem.
+    self assert: (Smalltalk allClasses includesIdentical: jclassI1) not.
+    self assert: (Smalltalk allClasses includesIdentical: jclassI2) not.
+    self assert: (Smalltalk allClasses includesIdentical: jclassA2) not.
+
+    [
+        jinstB foo.
+        self assert: false "/ should raise ClassNotFoundException
+    ] on: JAVA java lang ClassNotFoundException do:[
+        self assert: true.
+    ].
+
+    jclassA2 := self compileAndRegister:'
+public class test_unloading_01_A2 { 
+    public int bar() {
+        return 20;
+    }
+}'.
+
+    self assert: jinstB foo == 20.
+
+    "Created: / 14-09-2013 / 19:04:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 15-09-2013 / 00:40:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!JavaClassReloaderTests class methodsFor:'documentation'!
+
+version_CVS
+    ^ '$Header: /cvs/stx/stx/libjava/experiments/ClassReloadingTests.st,v 1.2 2013-02-25 11:15:34 vrany Exp $'
+!
+
+version_HG
+
+    ^ '$Changeset: <not expanded> $'
+!
+
+version_SVN
+    ^ '§Id::                                                                                                                        §'
+! !
+