| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 |
| |
| /** |
| * Tests the use of properties in Groovy |
| */ |
| class PropertyTest extends GroovyTestCase { |
| |
| void testNormalPropertyGettersAndSetters() { |
| def foo = new Foo() |
| def value = foo.getMetaClass() |
| |
| assert foo.name == "James" |
| assert foo.getName() == "James" |
| assert foo.location == "London" |
| assert foo.getLocation() == "London" |
| assert foo.blah == 9 |
| assert foo.getBlah() == 9 |
| |
| foo.name = "Bob" |
| foo.location = "Atlanta" |
| |
| assert foo.name == "Bob" |
| assert foo.getName() == "Bob" |
| assert foo.location == "Atlanta" |
| assert foo.getLocation() == "Atlanta" |
| } |
| |
| // GROOVY-1809 |
| void testClassWithPrivateFieldAndGetter() { |
| if (HeadlessTestSupport.headless) return |
| assert java.awt.Font.getName() == 'java.awt.Font' |
| assert java.awt.Font.name == 'java.awt.Font' |
| } |
| |
| void testOverloadedGetter() { |
| def foo = new Foo() |
| assert foo.getCount() == 1 |
| assert foo.count == 1 |
| foo.count = 7 |
| assert foo.count == 7 |
| assert foo.getCount() == 7 |
| } |
| |
| void testNoSetterAvailableOnPrivateProperty() { |
| def foo = new Foo() |
| |
| // methods should fail on non-existent method calls |
| //shouldFail { foo.blah = 4 } |
| shouldFail { foo.setBlah(4) } |
| } |
| |
| void testCannotSeePrivateProperties() { |
| def foo = new Foo() |
| |
| // def access fails on non-existent def |
| //shouldFail { def x = foo.invisible } //todo: correct handling of access rules |
| |
| // methods should fail on non-existent method calls |
| shouldFail { foo.getQ() } |
| } |
| |
| void testConstructorWithNamedProperties() { |
| def foo = new Foo(name: 'Gromit', location: 'Moon') |
| |
| assert foo.name == 'Gromit' |
| assert foo.location == 'Moon' |
| } |
| |
| void testToString() { |
| def foo = new Foo(name: 'Gromit', location: 'Moon') |
| assert foo.toString().endsWith('name: Gromit location: Moon') |
| } |
| |
| void testArrayLengthProperty() { |
| // create two arrays, since all use the same MetaArrayLengthProperty object - |
| // make sure it can work for all types and sizes |
| def i = new Integer[5] |
| def s = new String[10] |
| |
| // put something in it to make sure we're returning the *allocated* length, and |
| // not the *used* length |
| s[0] = "hello" |
| |
| assert i.length == 5 |
| assert s.length == 10 |
| |
| // this def does not mean there is a getLength() method |
| shouldFail { i.getLength() } |
| |
| // verify we can't set this def, it's read-only |
| shouldFail { i.length = 6 } |
| } |
| |
| void testGstringAssignment() { |
| def foo = new Foo() |
| foo.body = "${foo.name}" |
| assert foo.body == "James" |
| } |
| |
| void testFinalProperty() { |
| def shell = new GroovyShell(); |
| assertScript """ |
| class A { |
| final foo = 1 |
| } |
| A.class.declaredMethods.each { |
| assert it.name!="setFoo" |
| |
| } |
| assert new A().foo==1 |
| """ |
| shouldFail { |
| shell.execute """ |
| class A { |
| final foo = 1 |
| } |
| new A().foo = 2 |
| """ |
| } |
| } |
| |
| void testFinalField() { |
| def shell = new GroovyShell(); |
| shouldFail { |
| shell.execute """ |
| class A { |
| public final foo = 1 |
| } |
| new A().foo = 2 |
| """ |
| } |
| } |
| |
| void testFinalPropertyWithInheritance() { |
| def child = new Child() |
| assert child.finalProperty == 1 |
| child.finalProperty = 22 |
| assert child.finalProperty == 1 |
| } |
| |
| void testBaseProperties() { |
| assert new Child().field == 'foobar' |
| } |
| |
| // GROOVY-1736 |
| void testGetSuperProperties() { |
| def c = new Child() |
| assert c.thing == 'bar thing' |
| assert c.superthing() == 'bar1foo thing' |
| assert c.x() == 'bar2foo x' |
| assert c.xprop == 'bar3foo x prop' |
| assert c.xpropViaMethod == 'bar4foo x prop' |
| } |
| |
| void testSetSuperProperties() { |
| def c = new Child() |
| assert c.superField == 'bar' |
| c.setSuperField('baz1') |
| assert c.superField == 'baz1' |
| c.superField = 'baz2' |
| assert c.superField == 'baz2' |
| |
| assert c.superthing() == 'bar1foo thing' |
| c.superThing = 'bar thing' |
| assert c.superthing() == 'bar1bar thing' |
| } |
| |
| void testOverwritingNormalProperty() { |
| def c = new Child() |
| assert c.normalProperty == 2 |
| } |
| |
| //GROOVY-2244 |
| void testWriteOnlyBeanProperty() { |
| def bean = new Child() |
| |
| // assert the property exists |
| assert bean.metaClass.properties.findAll { it.name == 'superThing' } |
| |
| // attempt to write to it |
| bean.superThing = 'x' |
| |
| // attempt to read it |
| shouldFail(MissingPropertyException) { |
| fail("We shouldn't be able to read bean.superThing, but we can: '$bean.superThing'") |
| } |
| } |
| |
| void testPrivatePropertyThroughSubclass() { |
| assertScript ''' |
| class A { |
| private getFoo(){1} |
| def bar(){return foo} |
| } |
| class B extends A {} |
| |
| def b = new B() |
| assert b.bar()==1 |
| ''' |
| } |
| |
| void testPropertyWithMultipleSetters() { |
| assertScript ''' |
| class A { |
| private field |
| void setX(Integer a) {field=a} |
| void setX(String b) {field=b} |
| def getX(){field} |
| } |
| def a = new A() |
| a.x = 1 |
| assert a.x==1 |
| a.x = "3" |
| assert a.x == "3" |
| ''' |
| } |
| |
| void testOverrideMultiSetterThroughMetaClass() { |
| assertScript ''' |
| class A { |
| private String field |
| void setConstraints(Closure cl) {} |
| void setConstraints(String s) {} |
| String getField() { field } |
| } |
| |
| A.metaClass.setConstraints = { delegate.field = it+it } |
| def a = new A() |
| a.constraints = '100' |
| assert a.field == '100100' |
| ''' |
| } |
| } |
| |
| class Base { |
| protected String field = 'bar' |
| |
| protected thing = 'foo thing' |
| |
| def getXprop() { 'foo x prop' } |
| |
| def x() { 'foo x' } |
| |
| void setThing(value) { thing = value } |
| |
| //testing final property getter |
| final getFinalProperty() { 1 } |
| |
| // testing normal property |
| def normalProperty = 1 |
| } |
| |
| class Child extends Base { |
| protected String field = 'foo' + super.field |
| |
| def getField() { field } |
| |
| void setSuperField(value) { super.field = value } |
| |
| def getSuperField() { super.field } |
| |
| def thing = 'bar thing' |
| |
| def superthing() { |
| 'bar1' + super.thing |
| } |
| |
| def x() { |
| 'bar2' + super.x() |
| } |
| |
| def getXprop() { |
| 'bar3' + super.xprop |
| } |
| |
| def getXpropViaMethod() { |
| 'bar4' + super.getXprop() |
| } |
| |
| def setSuperThing(value) { |
| super.thing = value |
| } |
| |
| // testing final property getter |
| // the following property should not add a new getter |
| // method, this would result in a verify error |
| def finalProperty = 32 |
| |
| // testing overwriting normal property |
| def normalProperty = 2 |
| } |