|
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.