001: /*
002: * $Id: InvokeMethodTest.java 4099 2006-10-10 18:06:52Z blackdrag $
003: *
004: * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
005: *
006: * Redistribution and use of this software and associated documentation
007: * ("Software"), with or without modification, are permitted provided that the
008: * following conditions are met:
009: * 1. Redistributions of source code must retain copyright statements and
010: * notices. Redistributions must also contain a copy of this document.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. The name "groovy" must not be used to endorse or promote products
015: * derived from this Software without prior written permission of The Codehaus.
016: * For written permission, please contact info@codehaus.org.
017: * 4. Products derived from this Software may not be called "groovy" nor may
018: * "groovy" appear in their names without prior written permission of The
019: * Codehaus. "groovy" is a registered trademark of The Codehaus.
020: * 5. Due credit should be given to The Codehaus - http://groovy.codehaus.org/
021: *
022: * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
023: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
024: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
025: * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
026: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
027: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
028: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
029: * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
030: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
031: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
032: * DAMAGE.
033: *
034: */
035:
036: package org.codehaus.groovy.runtime;
037:
038: import groovy.lang.GString;
039: import groovy.lang.GroovyRuntimeException;
040: import groovy.lang.IntRange;
041: import groovy.util.GroovyTestCase;
042:
043: import java.math.BigDecimal;
044: import java.text.SimpleDateFormat;
045: import java.util.ArrayList;
046: import java.util.Arrays;
047: import java.util.Collection;
048: import java.util.Date;
049: import java.util.List;
050:
051: import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
052:
053: import junit.framework.AssertionFailedError;
054:
055: /**
056: * Tests method invocation
057: *
058: * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
059: * @version $Revision: 4099 $
060: */
061: public class InvokeMethodTest extends GroovyTestCase {
062:
063: protected Invoker invoker = InvokerHelper.getInstance();
064:
065: // Method invocation tests
066: //-------------------------------------------------------------------------
067:
068: public void testInvokeMethodNoParams() throws Throwable {
069: Object value = invoke(this , "mockCallWithNoParams", null);
070: assertEquals("return value", "NoParams", value);
071:
072: value = invoke(this , "mockCallWithNoParams", new Object[0]);
073: assertEquals("return value", "NoParams", value);
074: }
075:
076: public void testInvokeMethodOneParam() throws Throwable {
077: Object value = invoke(this , "mockCallWithOneParam", "abc");
078: assertEquals("return value", "OneParam", value);
079: }
080:
081: public void testInvokeMethodOneParamWhichIsNull() throws Throwable {
082: Object value = invoke(this , "mockCallWithOneNullParam",
083: new Object[] { null });
084: assertEquals("return value", "OneParamWithNull", value);
085:
086: value = invoke(this , "mockCallWithOneNullParam", null);
087: assertEquals("return value", "OneParamWithNull", value);
088: }
089:
090: public void testInvokeOverloadedMethodWithOneParamWhichIsNull()
091: throws Throwable {
092: Object value = invoke(this , "mockOverloadedMethod",
093: new Object[] { null });
094: assertEquals("return value", "Object", value);
095: }
096:
097: public void testInvokeMethodOneCollectionParameter()
098: throws Throwable {
099: Object[] foo = { "a", "b", "c" };
100:
101: Object value = invoke(this , "mockCallWithOneCollectionParam",
102: new Object[] { foo });
103: assertEquals("return value", new Integer(3), value);
104:
105: List list = new ArrayList();
106: list.add("a");
107: list.add("b");
108: value = invoke(this , "mockCallWithOneCollectionParam", list);
109: assertEquals("return value", new Integer(2), value);
110: }
111:
112: public void testInvokePrintlnMethod() throws Throwable {
113: Object value = invoke(System.out, "println",
114: "testing System.out.println...");
115: assertEquals("return value", null, value);
116: }
117:
118: public void testMethodChooserNull() throws Throwable {
119: assertMethodChooser("Object", new Object[] { null });
120: }
121:
122: public void testMethodChooserNoParams() throws Throwable {
123: assertMethodChooser("void", null);
124: }
125:
126: public void testMethodChooserObject() throws Throwable {
127: assertMethodChooser("Object", new Object());
128: assertMethodChooser("Object", new Date());
129: }
130:
131: public void testMethodChooserString_FAILS() throws Throwable {
132: if (notYetImplemented())
133: return;
134: assertMethodChooser("String", "foo");
135: assertMethodChooser("String", new StringBuffer());
136: assertMethodChooser("String", new Character('a'));
137: }
138:
139: public void testMethodChooserNumber() throws Throwable {
140: assertMethodChooser("Number", new Integer(2));
141: assertMethodChooser("Number", new Double(2));
142: }
143:
144: public void testMethodChooserTwoParams() throws Throwable {
145: List list = new ArrayList();
146: list.add("foo");
147: list.add("bar");
148: assertMethodChooser("Object,Object", list.toArray());
149:
150: Object[] blah = { "a", "b" };
151: assertMethodChooser("Object,Object", blah);
152: }
153:
154: public void testInstanceofWorksForArray() {
155: Class type = Object[].class;
156: Object value = new Object[1];
157: assertTrue("instanceof works for array", type.isInstance(value));
158: }
159:
160: public void testMethodChooserTwoParamsWithSecondAnObjectArray()
161: throws Throwable {
162: Object[] blah = { "a", new Object[] { "b" } };
163: assertMethodChooser("Object,Object[]", blah);
164: }
165:
166: public void testCollectionMethods() throws Throwable {
167: Object list = InvokerHelper
168: .createList(new Object[] { "a", "b" });
169:
170: Object value = invoke(list, "size", null);
171: assertEquals("size of collection", new Integer(2), value);
172:
173: value = invoke(list, "contains", "a");
174: assertEquals("contains method", Boolean.TRUE, value);
175: }
176:
177: public void testNewMethods() throws Throwable {
178: Object value = invoke("hello", "size", null);
179: assertEquals("size of string", new Integer(5), value);
180: }
181:
182: public void testStaticMethod() throws Throwable {
183: Object value = invoke(DummyBean.class, "dummyStaticMethod",
184: "abc");
185: assertEquals("size of string", "ABC", value);
186: }
187:
188: public void testBaseClassMethod() throws Throwable {
189: Object object = new DummyBean();
190: Object value = invoke(object, "toString", null);
191: assertEquals("toString", object.toString(), value);
192: }
193:
194: //SPG modified to reflect DefaultGroovyMethod name change and expected result from
195: //Integer/Integer division.
196: public void testDivideNumbers() throws Throwable {
197: assertMethodCall(new Double(10), "div", new Double(2),
198: new Double(5));
199: assertMethodCall(new Double(10), "div", new Integer(2),
200: new Double(5));
201: assertMethodCall(new Integer(10), "div", new Double(2),
202: new Double(5));
203: assertMethodCall(new Integer(10), "div", new Integer(2),
204: new java.math.BigDecimal("5"));
205: }
206:
207: public void testBaseFailMethod() throws Throwable {
208: try {
209: invoke(this , "fail", "hello");
210: } catch (AssertionFailedError e) {
211: // worked
212: }
213: }
214:
215: public void testToArrayOnList() throws Throwable {
216: List object = new ArrayList();
217: object.add("Hello");
218:
219: Object[] value = (Object[]) invoke(object, "toArray", null);
220: assertArrayEquals(object.toArray(), value);
221: assertEquals(1, value.length);
222: assertEquals("Hello", value[0]);
223:
224: value = (Object[]) invoke(object, "toArray", new Object[0]);
225: assertArrayEquals(object.toArray(), value);
226: }
227:
228: public void testInvalidOverloading() throws Throwable {
229: try {
230: invoke(this , "badOverload", new Object[] { "a", "b" });
231: fail("Should fail as an unambiguous method is invoked");
232: } catch (GroovyRuntimeException e) {
233: System.out.println("Caught: " + e);
234: }
235: }
236:
237: public void testPlusWithNull() throws Throwable {
238: String param = "called with: ";
239: Object value = invoke(param, "plus", new Object[] { null });
240: assertEquals("called with null", param + null, value);
241: }
242:
243: public void testCallIntMethodWithInteger() throws Throwable {
244: Object value = invoke(this , "overloadedRemove",
245: new Object[] { new Integer(5) });
246: assertEquals("called with integer", "int5", value);
247: }
248:
249: public void testCallListRemove() throws Throwable {
250: List list = new ArrayList();
251: list.add("foo");
252: list.add("bar");
253:
254: invoke(list, "remove", new Object[] { new Integer(0) });
255:
256: assertEquals("Should have just 1 item left: " + list, 1, list
257: .size());
258: }
259:
260: public void testCoerceGStringToString() throws Throwable {
261: GString param = new GString(new Object[] { "James" }) {
262: public String[] getStrings() {
263: return new String[] { "Hello " };
264: }
265: };
266: Object value = invoke(this , "methodTakesString",
267: new Object[] { param });
268: assertEquals("converted GString to string", param.toString(),
269: value);
270: }
271:
272: public void testCoerceGStringToStringOnGetBytes() throws Throwable {
273: GString param = new GString(new Object[] { "US-ASCII" }) {
274: public String[] getStrings() {
275: return new String[] { "" };
276: }
277: };
278: Object value = invoke("test", "getBytes",
279: new Object[] { param });
280: assertEquals("converted GString to string", "test".getBytes(
281: "US-ASCII").getClass(), value.getClass());
282: }
283:
284: public void testBadBDToDoubleCoerce() throws Throwable {
285: try {
286: invoke(Math.class, "floor", new BigDecimal("1.7E309"));
287: } catch (IllegalArgumentException e) {
288: assertTrue(
289: "Math.floor(1.7E309) should fail because it is out of range for a Double. "
290: + e,
291: e.getMessage().indexOf("out of range") > 0);
292: return;
293: }
294: fail("Math.floor(1.7E309) should fail because it is out of range for a Double.");
295: }
296:
297: public void testClassMethod() throws Throwable {
298: Class c = String.class;
299: Object value = invoke(c, "getName", null);
300: assertEquals("Class.getName()", c.getName(), value);
301: c = getClass();
302: value = invoke(c, "getName", null);
303: assertEquals("Class.getName()", c.getName(), value);
304: }
305:
306: public void testProtectedMethod() throws Throwable {
307: String param = "hello";
308: Object value = invoke(this , "aProtectedMethod", param);
309: assertEquals("protected method call", aProtectedMethod(param),
310: value);
311: }
312:
313: public void testPrivateMethod() throws Throwable {
314: String param = "hello";
315: Object value = invoke(this , "aPrivateMethod", param);
316: assertEquals("private method call", aPrivateMethod(param),
317: value);
318: }
319:
320: public void testStringSubstringMethod() throws Throwable {
321: String object = "hello";
322: Object value = invoke(object, "substring", new Integer(2));
323: assertEquals("substring(2)", object.substring(2), value);
324:
325: value = invoke(object, "substring", new Object[] {
326: new Integer(1), new Integer(3) });
327: assertEquals("substring(1,3)", object.substring(1, 3), value);
328: }
329:
330: public void testListGetWithRange() throws Throwable {
331: List list = Arrays.asList(new Object[] { "a", "b", "c" });
332: Object range = new IntRange(0, 2);
333: Object value = invoke(list, "getAt", range);
334: assertTrue("Returned List: " + value, value instanceof List);
335: List retList = (List) value;
336: assertEquals("List size", 3, retList.size());
337: }
338:
339: public void testSetLenientOnDateFormat() throws Throwable {
340: SimpleDateFormat a = new SimpleDateFormat("MM/dd/yyyy");
341:
342: Object value = invoke(a, "setLenient",
343: new Object[] { Boolean.FALSE });
344: assertEquals("void method", null, value);
345: }
346:
347: public void testInvokeUnknownMethod() throws Throwable {
348: try {
349: Object value = invoke(this , "unknownMethod", "abc");
350: fail("Should have thrown an exception");
351: } catch (GroovyRuntimeException e) {
352: // worked
353: }
354: }
355:
356: public void testInvokeMethodWithWrongNumberOfParameters()
357: throws Throwable {
358: try {
359: Object[] args = { "a", "b" };
360: invoke(this , "unknownMethod", args);
361: fail("Should have thrown an exception");
362: } catch (GroovyRuntimeException e) {
363: // worked
364: }
365: }
366:
367: public void testInvokeMethodOnNullObject() throws Throwable {
368: try {
369: invoke(null, "mockCallWithNoParams", null);
370: fail("Should have thrown an exception");
371: } catch (NullPointerException e) {
372: // worked
373: }
374: }
375:
376: // Mock methods used for testing
377: //-------------------------------------------------------------------------
378:
379: public Object mockCallWithNoParams() {
380: return "NoParams";
381: }
382:
383: public Object mockCallWithOneParam(Object value) {
384: assertEquals("Method not passed in the correct value", "abc",
385: value);
386: return "OneParam";
387: }
388:
389: public Object mockCallWithOneNullParam(Object value) {
390: assertEquals("Method not passed in the correct value", null,
391: value);
392: return "OneParamWithNull";
393: }
394:
395: public Integer mockCallWithOneCollectionParam(Object collection) {
396: Collection coll = DefaultTypeTransformation
397: .asCollection(collection);
398: return new Integer(coll.size());
399: }
400:
401: public Object mockOverloadedMethod() {
402: return "void";
403: }
404:
405: public Object mockOverloadedMethod(Object object) {
406: return "Object";
407: }
408:
409: public Object mockOverloadedMethod(Number object) {
410: return "Number";
411: }
412:
413: public Object mockOverloadedMethod(String object) {
414: return "String";
415: }
416:
417: public Object mockOverloadedMethod(Object object, Object bar) {
418: return "Object,Object";
419: }
420:
421: public Object mockOverloadedMethod(Object object, Object[] array) {
422: return "Object,Object[]";
423: }
424:
425: public Object badOverload(String a, Object b) {
426: return "String, Object";
427: }
428:
429: public Object badOverload(Object a, String b) {
430: return "Object, String";
431: }
432:
433: public Object methodTakesString(String x) {
434: return x;
435: }
436:
437: public Object overloadedRemove(int idx) {
438: return "int" + idx;
439: }
440:
441: public Object overloadedRemove(Object value) {
442: return "Object" + value;
443: }
444:
445: // Implementation methods
446: //-------------------------------------------------------------------------
447:
448: protected Object aProtectedMethod(String param) {
449: return param + " there!";
450: }
451:
452: private Object aPrivateMethod(String param) {
453: return param + " James!";
454: }
455:
456: protected void assertMethodCall(Object object, String method,
457: Object param, Object expected) {
458: Object value = InvokerHelper.invokeMethod(object, method,
459: new Object[] { param });
460: assertEquals("result of method: " + method, expected, value);
461: }
462:
463: /**
464: * Asserts that invoking the method chooser finds the right overloaded
465: * method implementation
466: *
467: * @param expected
468: * is the expected value of the method
469: * @param arguments
470: * the argument(s) to the method invocation
471: */
472: protected void assertMethodChooser(Object expected, Object arguments)
473: throws Throwable {
474: Object value = invoke(this , "mockOverloadedMethod", arguments);
475:
476: assertEquals("Invoking overloaded method for arguments: "
477: + InvokerHelper.toString(arguments), expected, value);
478: }
479:
480: protected Object invoke(Object object, String method, Object args)
481: throws Throwable {
482: try {
483: return invoker.invokeMethod(object, method, args);
484: } catch (InvokerInvocationException e) {
485: throw e.getCause();
486: }
487: }
488: }
|