|
Groovy example source code file (ExpandoMetaClassTest.groovy)
The Groovy ExpandoMetaClassTest.groovy source code/* * Copyright 2004-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package groovy.lang /** * @author Graeme Rocher */ class ExpandoMetaClassTest extends GroovyTestCase { void testMethodsAfterAddingNewMethod() { EMCT_Class.metaClass.newMethod = {-> "foo" } def methods = EMCT_Class.metaClass.methods.findAll {it.name == "newMethod"} assert methods assertEquals 1, methods.size() EMCT_Class.metaClass.newMethod = {-> "foo" } methods = EMCT_Class.metaClass.methods.findAll {it.name == "newMethod"} assert methods assertEquals 1, methods.size() } void testPropertiesAfterAddingProperty() { EMCT_Class.metaClass.getNewProp = {-> "foo" } def props = EMCT_Class.metaClass.properties.findAll {it.name == "newProp"} assert props assertEquals 1, props.size() EMCT_Class.metaClass.setNewProp = {String txt -> } props = EMCT_Class.metaClass.properties.findAll {it.name == "newProp"} assert props assertEquals 1, props.size() } void testOverrideStaticMethod() { EMCT_Static.metaClass.'static'.f = { "first" } assertEquals "first", EMCT_Static.f("") EMCT_Static.metaClass.'static'.f = { "second" } assertEquals "second", EMCT_Static.f("") } void testOverrideMethod() { EMCT_Static.metaClass.f = { "first" } assertEquals "first", new EMCT_Static().f("") EMCT_Static.metaClass.f = { "second" } assertEquals "second", new EMCT_Static().f("") } void testStaticBeanStyleProperties() { def mc = new ExpandoMetaClass(EMCT_InvokeMethod.class, true, true) mc.initialize() GroovySystem.metaClassRegistry.setMetaClass(EMCT_InvokeMethod.class, mc) mc.'static'.getHello = {-> "bar!"} assertEquals "bar!", EMCT_InvokeMethod.hello } void testOverrideInvokeStaticMethod() { def mc = new ExpandoMetaClass(EMCT_InvokeMethod.class, true, true) mc.initialize() GroovySystem.metaClassRegistry.setMetaClass(EMCT_InvokeMethod.class, mc) mc.'static'.invokeMethod = {String methodName, args -> def metaMethod = mc.getStaticMetaMethod(methodName, args) def result = null if (metaMethod) result = metaMethod.invoke(delegate, args) else { result = "foo!" } result } assertEquals "bar!", EMCT_InvokeMethod.myStaticMethod() assertEquals "foo!", EMCT_InvokeMethod.dynamicMethod() } void testOverrideInvokeMethod() { def mc = new ExpandoMetaClass(EMCT_InvokeMethod.class, false, true) mc.initialize() assert mc.hasMetaMethod("invokeMe", [String] as Class[]) mc.invokeMethod = {String name, args -> def mm = delegate.metaClass.getMetaMethod(name, args) mm ? mm.invoke(delegate, args) : "bar!!" } def t = new EMCT_InvokeMethod() t.metaClass = mc assertEquals "bar!!", t.doStuff() assertEquals "Foo!! hello", t.invokeMe("hello") } void testOverrideSetProperty() { def mc = new ExpandoMetaClass(EMCT_GetProperty.class, false, true) mc.initialize() assert mc.hasMetaProperty("name") def testValue = null mc.setProperty = {String name, value -> def mp = delegate.metaClass.getMetaProperty(name) if (mp) {mp.setProperty(delegate, value)} else {testValue = value} } def t = new EMCT_GetProperty() t.metaClass = mc t.name = "Bob" assertEquals "Bob", t.name t.foo = "bar" assertEquals "bar", testValue } void testOverrideGetProperty() { def mc = new ExpandoMetaClass(EMCT_GetProperty.class, false, true) mc.initialize() assert mc.hasMetaProperty("name") mc.getProperty = {String name -> def mp = delegate.metaClass.getMetaProperty(name) mp ? mp.getProperty(delegate) : "foo $name" } def t = new EMCT_GetProperty() t.metaClass = mc assertEquals "foo bar", t.getProperty("bar") assertEquals "foo bar", t.bar assertEquals "Fred", t.getProperty("name") assertEquals "Fred", t.name } void testBooleanGetterWithClosure() { def metaClass = new ExpandoMetaClass(EMCT_Class.class, false, true) metaClass.initialize() metaClass.isValid = {-> true} def t = new EMCT_Class() t.metaClass = metaClass assert t.isValid() assert t.valid } void testAllowAdditionOfProperties() { def metaClass = new ExpandoMetaClass(EMCT_Class.class, false, true) metaClass.getOne << {-> "testme" } metaClass.initialize() try { metaClass.getTwo << {-> "testagain" } } catch (RuntimeException e) { fail("Should have allowed addition of new method") } def t = new EMCT_Class() t.metaClass = metaClass assertEquals "testme", t.one assertEquals "testagain", t.two } void testAllowAdditionOfMethods() { def metaClass = new ExpandoMetaClass(EMCT_Class.class, false, true) metaClass.myMethod << {-> "testme" } metaClass.initialize() try { metaClass.mySecondMethod << {-> "testagain" } } catch (RuntimeException e) { fail("Should have allowed addition of new method") } def t = new EMCT_Class() t.metaClass = metaClass assertEquals "testme", t.myMethod() assertEquals "testagain", t.mySecondMethod() } void testForbiddenAdditionOfMethods() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) metaClass.myMethod << { "testme" } metaClass.initialize() def t = new EMCT_Class() try { metaClass.mySecondMethod << { "testagain" } fail("Should have thrown exception") } catch (RuntimeException e) { // expected } } void testPropertyGetterWithClosure() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) metaClass.getSomething = {-> "testme"} metaClass.initialize() def t = new EMCT_Class() t.metaClass = metaClass assertEquals "testme", t.getSomething() assertEquals "testme", t.something } void testPropertySetterWithClosure() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) def testSet = null metaClass.setSomething = {String txt -> testSet = txt} metaClass.initialize() def t = new EMCT_Class() t.metaClass = metaClass t.something = "testme" assertEquals "testme", testSet t.setSomething("test2") assertEquals "test2", testSet } void testNewMethodOverloading() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) metaClass.overloadMe << {String txt -> txt} << {Integer i -> i} metaClass.initialize() def t = new EMCT_Class() t.metaClass = metaClass assertEquals "test", t.overloadMe("test") assertEquals 10, t.overloadMe(10) } void testOverloadExistingMethodAfterInitialize() { def t = new EMCT_Class() assertEquals "test", t.doSomething("test") def metaClass = new ExpandoMetaClass(EMCT_Class.class, false, true) metaClass.initialize() metaClass.doSomething = {Integer i -> i + 1} t.metaClass = metaClass assertEquals "test", t.doSomething("test") assertEquals 11, t.doSomething(10) } void testOverloadExistingMethodBeforeInitialize() { def t = new EMCT_Class() assertEquals "test", t.doSomething("test") def metaClass = new ExpandoMetaClass(EMCT_Class.class, false, true) metaClass.doSomething = {Integer i -> i + 1} metaClass.initialize() t.metaClass = metaClass assertEquals "test", t.doSomething("test") assertEquals 11, t.doSomething(10) } void testNewPropertyMethod() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) metaClass.something = "testme" metaClass.initialize() def t = new EMCT_Class() t.metaClass = metaClass assertEquals "testme", t.getSomething() assertEquals "testme", t.something t.something = "test2" assertEquals "test2", t.something assertEquals "test2", t.getSomething() def t2 = new EMCT_Class() t2.metaClass = metaClass // now check that they're not sharing the same property! assertEquals "testme", t2.something assertEquals "test2", t.something t2.setSomething("test3") assertEquals "test3", t2.something } void testCheckFailOnExisting() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) try { metaClass.existing << {-> "should fail. already exists!" } fail("Should have thrown exception when method already exists") } catch (Exception e) { // expected } } void testCheckFailOnExistingConstructor() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) try { metaClass.constructor << {-> "should fail. already exists!" } fail("Should have thrown exception when method already exists") } catch (Exception e) { // expected } } void testCheckFailOnExistingStaticMethod() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) try { metaClass.'static'.existingStatic << {-> "should fail. already exists!" } fail("Should have thrown exception when method already exists") } catch (Exception e) { // expected } } void testNewStaticMethod() { def metaClass = new ExpandoMetaClass(EMCT_Class.class, true) metaClass.'static'.myStaticMethod << {String txt -> "testme" } metaClass.initialize() assertEquals "testme", EMCT_Class.myStaticMethod("blah") } void testReplaceStaticMethod() { def metaClass = new ExpandoMetaClass(EMCT_Class.class, true) metaClass.'static'.existingStatic = {-> "testme" } metaClass.initialize() assertEquals "testme", EMCT_Class.existingStatic() } void testNewZeroArgumentStaticMethod() { def metaClass = new ExpandoMetaClass(EMCT_Class.class, true) metaClass.'static'.myStaticMethod = {-> "testme" } metaClass.initialize() assertEquals "testme", EMCT_Class.myStaticMethod() } void testNewInstanceMethod() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) metaClass.myMethod << { "testme" } metaClass.initialize() def t = new EMCT_Class() t.metaClass = metaClass assertEquals "testme", t.myMethod() } void testNewConstructor() { def metaClass = new ExpandoMetaClass(EMCT_Class.class, true) metaClass.constructor << {String txt -> def t = EMCT_Class.class.newInstance() t.name = txt return t } metaClass.initialize() def t = new EMCT_Class("testme") assert t assertEquals "testme", t.name GroovySystem.metaClassRegistry.removeMetaClass(EMCT_Class.class) } void testReplaceConstructor() { def metaClass = new ExpandoMetaClass(EMCT_Class.class, true) metaClass.constructor = {-> "testme" } metaClass.initialize() def t = new EMCT_Class() assert t assertEquals "testme", t GroovySystem.metaClassRegistry.removeMetaClass(EMCT_Class.class) } void testReplaceInstanceMethod() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) metaClass.existing2 = {Object i -> "testme" } metaClass.initialize() def t = new EMCT_Class() t.metaClass = metaClass def var = 1 assertEquals "testme", t.existing2(var) } void testBorrowMethodFromAnotherClass() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) def a = new EMCT_Another() metaClass.borrowMe = a.&another metaClass.borrowMeToo = a.&noArgs metaClass.initialize() def t = new EMCT_Class() t.metaClass = metaClass assertEquals "mine blah!", t.borrowMe("blah") assertEquals "mine blah+foo!", t.borrowMe("blah", "foo") // GROOVY-1993 assertEquals "no args here!", t.borrowMeToo() } void testClosureWithOptionalArgs() { def metaClass = new ExpandoMetaClass(EMCT_Class.class) metaClass.withOptional { String first, String second = "no param" -> "$first + $second" } def t = new EMCT_Class() t.metaClass = metaClass assertEquals("blah + no param", t.withOptional("blah")) assertEquals("blah + foo", t.withOptional("blah", "foo")) } void testBorrowByName() { println 'testBorrowByName' def metaClass = new ExpandoMetaClass(EMCT_Class.class) def a = new EMCT_Another() metaClass.borrowMe = a.&'another' metaClass.borrowMeToo = a.&'noArgs' metaClass.initialize() def t = new EMCT_Class() t.metaClass = metaClass assertEquals "mine blah!", t.borrowMe("blah") // GROOVY-1993 assertEquals "no args here!", t.borrowMeToo() } void testAddIdenticalPropertyToChildAndParent() { ExpandoMetaClass.enableGlobally() doMethods(EMCT_SuperClass.class) doMethods(EMCT_ChildClass.class) def child = new EMCT_ChildClass() def parent = new EMCT_SuperClass() assert parent.errors == null parent.errors = [3, 2, 1, 0] assert parent.errors.size() == 4 assert child.errors == null child.errors = [1, 2, 3] assert child.errors.size() == 3 ExpandoMetaClass.disableGlobally() } void testMissingPropertyClosure() { assertScript """ class Circle { String prop1 = 'value1' } ExpandoMetaClass emc = new ExpandoMetaClass(this.class, false) emc.methodMissing = {String name, args -> throw new MissingMethodException(name, Script, args) } emc.propertyMissing = {String name -> throw new MissingPropertyException(name, Script) } emc.initialize() this.metaClass = emc Circle circle = new Circle() // closure will try to access prop1 on script, which does not have such // a property, thus a MissingPropertyException will be thrown // causing the closure code to select the delegate to resolve the property Closure cl = {prop1} cl.delegate = circle assert cl.call()=='value1' """ } void testMissingMethodClosure() { assertScript """ class Circle { def m1(){1} } ExpandoMetaClass emc = new ExpandoMetaClass(this.class, false) emc.methodMissing = {String name, args -> throw new MissingMethodException(name, Script, args) } emc.propertyMissing = {String name -> throw new MissingPropertyException(name, Script) } emc.initialize() this.metaClass = emc Circle circle = new Circle() // closure will try to call m1 on script, which does not have such // a method, thus a MissingMethodException will be thrown // causing the closure code to select the delegate to call the method Closure cl = {m1()} cl.delegate = circle assert cl.call() == 1 """ } void testMissingMethodExceptionThrownFromMissingMethod() { assertScript """ class Circle { def invokeMethodInvocations = 0 def invokeMethod(String name, Object[] args) { invokeMethodInvocations++; } def callNonExistingMethod() { m1() } } ExpandoMetaClass emc = new ExpandoMetaClass(Circle.class, false) def exception = new MissingMethodException("m1", Circle, null) emc.methodMissing = {String name, args -> throw exception } emc.initialize() Circle circle = new Circle() circle.metaClass = emc assert circle.invokeMethodInvocations == 0 def gotException=true try { circle.callNonExistingMethod() gotException=false } catch (MissingMethodException mme) { gotException=true assert mme == exception } assert gotException,"MissingMethodException expected, but got something else" assert circle.invokeMethodInvocations == 0 gotException=true try { circle.m1() gotException=false } catch (MissingMethodException mme) { assert mme == exception } assert gotException,"MissingMethodException expected, but got something else" """ } def doMethods(clazz) { def metaClass = clazz.metaClass metaClass.setErrors = {errors -> thingo = errors } metaClass.getErrors = {-> return thingo } } void testGetProperty() { def x = new EMCT_SuperClass() def mc = x.metaClass mc.getProperty = {String name -> MetaProperty mp = mc.getMetaProperty(name) if (mp) mp.getProperty(delegate) else { if (thingo) { thingo."$name" } else { if (application) { "non-null application" } else { String methodName = "get${name[0].toUpperCase()}${name.substring(1)}" mc."$methodName" = { -> "$name" } delegate."$methodName"() } } } } Map map = ["prop": "none"] x.thingo = map assertEquals map, x.thingo assertEquals("none", x.prop) x.thingo = null application = new Object() assertEquals("non-null application", x.prop) application = null assertEquals("prop", x.prop) application = new Object() assertEquals("prop", x.prop) } def application void testWithNull() { EMCT_SuperClass.metaClass = null ExpandoMetaClass.enableGlobally() def x = new EMCT_SuperClass() def mc = x.metaClass def request = new Object() request.metaClass { getFormat { -> "js" } } mc.render = {String txt -> txt } assertEquals("js", x.render(request.format)) ExpandoMetaClass.disableGlobally() } void testInterfaceWithGetProperty() { EMCT_Implemented.metaClass.getProperty = {String name -> return "META " + delegate.class.metaClass.getMetaProperty(name).getProperty(delegate) } EMCT_InterfaceWithFormat.metaClass.getFormat = { -> "js" } def x = new EMCT_Implemented() assertEquals "META js", x.format } void testPickMethodForVarg() { // as of 1.6 a metaClass is often the HandleMetaclass, which delegates // methods to an underlaying meta class. hasMethod is a Method on EMC // that takes a Class[] vargs argument as last part. If that part is not // given, then hasMetaMethod will still work, but the code actually // invoking the method in EMC.invokeMehod(String,Object) has to correct the // arguments. assert "".metaClass.pickMethod("trim") } void testEMCMetaClassProperty() { // GROOVY-2516 try { assert ExpandoMetaClass.class.metaClass instanceof MetaClass } finally { GroovySystem.metaClassRegistry.removeMetaClass(ExpandoMetaClass.class) } } void testDynamicAddedMethodWithGStringCall() { // GROOVY-4691 assertScript """ class A { def bar(x) { return {this."\$x"()} } } try { A.metaClass.foo = {->1} A.metaClass.methodMissing = { method, args -> 2} def a = new A() assert a.bar("foo")() == 1 assert a.x() == 2 } finally { GroovySystem.metaClassRegistry.removeMetaClass(A); } """ } } interface EMCT_InterfaceWithFormat { } class EMCT_Implemented implements EMCT_InterfaceWithFormat { } class EMCT_SuperClass { def thingo } class EMCT_ChildClass extends EMCT_SuperClass { } class EMCT_InvokeMethod { def invokeMe(String boo) {"Foo!! $boo"} static myStaticMethod() {"bar!"} } class EMCT_GetProperty { String name = "Fred" } class EMCT_Class { String name def existing2(obj) { "hello2!" } def existing() { "hello!" } def doSomething(Object txt) {txt} static existingStatic() { "I exist" } } class EMCT_Another { def another(txt, additional = "") { "mine ${txt}${additional ? '+' + additional : ''}!" } def noArgs() { "no args here!" } } class EMCT_Child extends EMCT_Class { def aChildMethod() { "hello children" } } class EMCT_Static {} Other Groovy examples (source code examples)Here is a short list of links related to this Groovy ExpandoMetaClassTest.groovy source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.