1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 package org.codehaus.groovy.runtime;
37
38 import groovy.lang.GString;
39 import groovy.lang.GroovyRuntimeException;
40 import groovy.lang.IntRange;
41 import groovy.util.GroovyTestCase;
42
43 import java.math.BigDecimal;
44 import java.text.SimpleDateFormat;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Collection;
48 import java.util.Date;
49 import java.util.List;
50
51 import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
52
53 import junit.framework.AssertionFailedError;
54
55 /***
56 * Tests method invocation
57 *
58 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
59 * @version $Revision: 4099 $
60 */
61 public class InvokeMethodTest extends GroovyTestCase {
62
63 protected Invoker invoker = InvokerHelper.getInstance();
64
65
66
67
68 public void testInvokeMethodNoParams() throws Throwable {
69 Object value = invoke(this, "mockCallWithNoParams", null);
70 assertEquals("return value", "NoParams", value);
71
72 value = invoke(this, "mockCallWithNoParams", new Object[0]);
73 assertEquals("return value", "NoParams", value);
74 }
75
76 public void testInvokeMethodOneParam() throws Throwable {
77 Object value = invoke(this, "mockCallWithOneParam", "abc");
78 assertEquals("return value", "OneParam", value);
79 }
80
81 public void testInvokeMethodOneParamWhichIsNull() throws Throwable {
82 Object value = invoke(this, "mockCallWithOneNullParam", new Object[] { null });
83 assertEquals("return value", "OneParamWithNull", value);
84
85 value = invoke(this, "mockCallWithOneNullParam", null);
86 assertEquals("return value", "OneParamWithNull", value);
87 }
88
89 public void testInvokeOverloadedMethodWithOneParamWhichIsNull() throws Throwable {
90 Object value = invoke(this, "mockOverloadedMethod", new Object[] { null });
91 assertEquals("return value", "Object", value);
92 }
93
94 public void testInvokeMethodOneCollectionParameter() throws Throwable {
95 Object[] foo = { "a", "b", "c" };
96
97 Object value = invoke(this, "mockCallWithOneCollectionParam", new Object[] { foo });
98 assertEquals("return value", new Integer(3), value);
99
100 List list = new ArrayList();
101 list.add("a");
102 list.add("b");
103 value = invoke(this, "mockCallWithOneCollectionParam", list);
104 assertEquals("return value", new Integer(2), value);
105 }
106
107 public void testInvokePrintlnMethod() throws Throwable {
108 Object value = invoke(System.out, "println", "testing System.out.println...");
109 assertEquals("return value", null, value);
110 }
111
112 public void testMethodChooserNull() throws Throwable {
113 assertMethodChooser("Object", new Object[] { null });
114 }
115
116 public void testMethodChooserNoParams() throws Throwable {
117 assertMethodChooser("void", null);
118 }
119
120 public void testMethodChooserObject() throws Throwable {
121 assertMethodChooser("Object", new Object());
122 assertMethodChooser("Object", new Date());
123 }
124
125 public void testMethodChooserString_FAILS() throws Throwable { if (notYetImplemented()) return;
126 assertMethodChooser("String", "foo");
127 assertMethodChooser("String", new StringBuffer());
128 assertMethodChooser("String", new Character('a'));
129 }
130
131 public void testMethodChooserNumber() throws Throwable {
132 assertMethodChooser("Number", new Integer(2));
133 assertMethodChooser("Number", new Double(2));
134 }
135
136 public void testMethodChooserTwoParams() throws Throwable {
137 List list = new ArrayList();
138 list.add("foo");
139 list.add("bar");
140 assertMethodChooser("Object,Object", list.toArray());
141
142 Object[] blah = { "a", "b" };
143 assertMethodChooser("Object,Object", blah);
144 }
145
146 public void testInstanceofWorksForArray() {
147 Class type = Object[].class;
148 Object value = new Object[1];
149 assertTrue("instanceof works for array", type.isInstance(value));
150 }
151
152 public void testMethodChooserTwoParamsWithSecondAnObjectArray() throws Throwable {
153 Object[] blah = { "a", new Object[] { "b" }
154 };
155 assertMethodChooser("Object,Object[]", blah);
156 }
157
158 public void testCollectionMethods() throws Throwable {
159 Object list = InvokerHelper.createList(new Object[] { "a", "b" });
160
161 Object value = invoke(list, "size", null);
162 assertEquals("size of collection", new Integer(2), value);
163
164 value = invoke(list, "contains", "a");
165 assertEquals("contains method", Boolean.TRUE, value);
166 }
167
168 public void testNewMethods() throws Throwable {
169 Object value = invoke("hello", "size", null);
170 assertEquals("size of string", new Integer(5), value);
171 }
172
173 public void testStaticMethod() throws Throwable {
174 Object value = invoke(DummyBean.class, "dummyStaticMethod", "abc");
175 assertEquals("size of string", "ABC", value);
176 }
177
178 public void testBaseClassMethod() throws Throwable {
179 Object object = new DummyBean();
180 Object value = invoke(object, "toString", null);
181 assertEquals("toString", object.toString(), value);
182 }
183
184
185
186 public void testDivideNumbers() throws Throwable {
187 assertMethodCall(new Double(10), "div", new Double(2), new Double(5));
188 assertMethodCall(new Double(10), "div", new Integer(2), new Double(5));
189 assertMethodCall(new Integer(10), "div", new Double(2), new Double(5));
190 assertMethodCall(new Integer(10), "div", new Integer(2), new java.math.BigDecimal("5"));
191 }
192
193 public void testBaseFailMethod() throws Throwable {
194 try {
195 invoke(this, "fail", "hello");
196 } catch (AssertionFailedError e) {
197
198 }
199 }
200
201 public void testToArrayOnList() throws Throwable {
202 List object = new ArrayList();
203 object.add("Hello");
204
205 Object[] value = (Object[]) invoke(object, "toArray", null);
206 assertArrayEquals(object.toArray(), value);
207 assertEquals(1, value.length);
208 assertEquals("Hello", value[0]);
209
210 value = (Object[]) invoke(object, "toArray", new Object[0]);
211 assertArrayEquals(object.toArray(), value);
212 }
213
214 public void testInvalidOverloading() throws Throwable {
215 try {
216 invoke(this, "badOverload", new Object[] { "a", "b" });
217 fail("Should fail as an unambiguous method is invoked");
218 }
219 catch (GroovyRuntimeException e) {
220 System.out.println("Caught: " + e);
221 }
222 }
223
224 public void testPlusWithNull() throws Throwable {
225 String param = "called with: ";
226 Object value = invoke(param, "plus", new Object[] { null });
227 assertEquals("called with null", param + null, value);
228 }
229
230 public void testCallIntMethodWithInteger() throws Throwable {
231 Object value = invoke(this, "overloadedRemove", new Object[] { new Integer(5)});
232 assertEquals("called with integer", "int5", value);
233 }
234
235 public void testCallListRemove() throws Throwable {
236 List list = new ArrayList();
237 list.add("foo");
238 list.add("bar");
239
240 invoke(list, "remove", new Object[] { new Integer(0)});
241
242 assertEquals("Should have just 1 item left: " + list, 1, list.size());
243 }
244
245 public void testCoerceGStringToString() throws Throwable {
246 GString param = new GString(new Object[] { "James" }) {
247 public String[] getStrings() {
248 return new String[] { "Hello " };
249 }
250 };
251 Object value = invoke(this, "methodTakesString", new Object[] { param });
252 assertEquals("converted GString to string", param.toString(), value);
253 }
254
255 public void testCoerceGStringToStringOnGetBytes() throws Throwable {
256 GString param = new GString(new Object[] { "US-ASCII" }) {
257 public String[] getStrings() {
258 return new String[] { "" };
259 }
260 };
261 Object value = invoke("test", "getBytes", new Object[] { param });
262 assertEquals("converted GString to string", "test".getBytes("US-ASCII").getClass(), value.getClass());
263 }
264
265 public void testBadBDToDoubleCoerce() throws Throwable {
266 try {
267 invoke(Math.class, "floor", new BigDecimal("1.7E309"));
268 } catch (IllegalArgumentException e) {
269 assertTrue("Math.floor(1.7E309) should fail because it is out of range for a Double. "
270 +e,e.getMessage().indexOf("out of range") > 0);
271 return;
272 }
273 fail("Math.floor(1.7E309) should fail because it is out of range for a Double.");
274 }
275
276 public void testClassMethod() throws Throwable {
277 Class c = String.class;
278 Object value = invoke(c, "getName", null);
279 assertEquals("Class.getName()", c.getName(), value);
280 c = getClass();
281 value = invoke(c, "getName", null);
282 assertEquals("Class.getName()", c.getName(), value);
283 }
284
285 public void testProtectedMethod() throws Throwable {
286 String param = "hello";
287 Object value = invoke(this, "aProtectedMethod", param);
288 assertEquals("protected method call", aProtectedMethod(param), value);
289 }
290
291 public void testPrivateMethod() throws Throwable {
292 String param = "hello";
293 Object value = invoke(this, "aPrivateMethod", param);
294 assertEquals("private method call", aPrivateMethod(param), value);
295 }
296
297 public void testStringSubstringMethod() throws Throwable {
298 String object = "hello";
299 Object value = invoke(object, "substring", new Integer(2));
300 assertEquals("substring(2)", object.substring(2), value);
301
302 value = invoke(object, "substring", new Object[] { new Integer(1), new Integer(3)});
303 assertEquals("substring(1,3)", object.substring(1, 3), value);
304 }
305
306 public void testListGetWithRange() throws Throwable {
307 List list = Arrays.asList(new Object[] { "a", "b", "c" });
308 Object range = new IntRange(0, 2);
309 Object value = invoke(list, "getAt", range);
310 assertTrue("Returned List: " + value, value instanceof List);
311 List retList = (List) value;
312 assertEquals("List size", 3, retList.size());
313 }
314
315 public void testSetLenientOnDateFormat() throws Throwable {
316 SimpleDateFormat a = new SimpleDateFormat( "MM/dd/yyyy" );
317
318 Object value = invoke(a, "setLenient", new Object[] { Boolean.FALSE });
319 assertEquals("void method", null, value);
320 }
321
322 public void testInvokeUnknownMethod() throws Throwable {
323 try {
324 Object value = invoke(this, "unknownMethod", "abc");
325 fail("Should have thrown an exception");
326 }
327 catch (GroovyRuntimeException e) {
328
329 }
330 }
331
332 public void testInvokeMethodWithWrongNumberOfParameters() throws Throwable {
333 try {
334 Object[] args = { "a", "b" };
335 invoke(this, "unknownMethod", args);
336 fail("Should have thrown an exception");
337 }
338 catch (GroovyRuntimeException e) {
339
340 }
341 }
342
343 public void testInvokeMethodOnNullObject() throws Throwable {
344 try {
345 invoke(null, "mockCallWithNoParams", null);
346 fail("Should have thrown an exception");
347 }
348 catch (NullPointerException e) {
349
350 }
351 }
352
353
354
355
356 public Object mockCallWithNoParams() {
357 return "NoParams";
358 }
359
360 public Object mockCallWithOneParam(Object value) {
361 assertEquals("Method not passed in the correct value", "abc", value);
362 return "OneParam";
363 }
364
365 public Object mockCallWithOneNullParam(Object value) {
366 assertEquals("Method not passed in the correct value", null, value);
367 return "OneParamWithNull";
368 }
369
370 public Integer mockCallWithOneCollectionParam(Object collection) {
371 Collection coll = DefaultTypeTransformation.asCollection(collection);
372 return new Integer(coll.size());
373 }
374
375 public Object mockOverloadedMethod() {
376 return "void";
377 }
378
379 public Object mockOverloadedMethod(Object object) {
380 return "Object";
381 }
382
383 public Object mockOverloadedMethod(Number object) {
384 return "Number";
385 }
386
387 public Object mockOverloadedMethod(String object) {
388 return "String";
389 }
390
391 public Object mockOverloadedMethod(Object object, Object bar) {
392 return "Object,Object";
393 }
394
395 public Object mockOverloadedMethod(Object object, Object[] array) {
396 return "Object,Object[]";
397 }
398
399 public Object badOverload(String a, Object b) {
400 return "String, Object";
401 }
402
403 public Object badOverload(Object a, String b) {
404 return "Object, String";
405 }
406
407 public Object methodTakesString(String x) {
408 return x;
409 }
410
411 public Object overloadedRemove(int idx) {
412 return "int" + idx;
413 }
414
415 public Object overloadedRemove(Object value) {
416 return "Object" + value;
417 }
418
419
420
421
422 protected Object aProtectedMethod(String param) {
423 return param + " there!";
424 }
425
426 private Object aPrivateMethod(String param) {
427 return param + " James!";
428 }
429
430 protected void assertMethodCall(Object object, String method, Object param, Object expected) {
431 Object value = InvokerHelper.invokeMethod(object, method, new Object[] { param });
432 assertEquals("result of method: " + method, expected, value);
433 }
434
435 /***
436 * Asserts that invoking the method chooser finds the right overloaded
437 * method implementation
438 *
439 * @param expected
440 * is the expected value of the method
441 * @param arguments
442 * the argument(s) to the method invocation
443 */
444 protected void assertMethodChooser(Object expected, Object arguments) throws Throwable {
445 Object value = invoke(this, "mockOverloadedMethod", arguments);
446
447 assertEquals("Invoking overloaded method for arguments: " + InvokerHelper.toString(arguments), expected, value);
448 }
449
450 protected Object invoke(Object object, String method, Object args) throws Throwable {
451 try {
452 return invoker.invokeMethod(object, method, args);
453 }
454 catch (InvokerInvocationException e) {
455 throw e.getCause();
456 }
457 }
458 }