VarargsTest.java revision 10093:056cd206a147
1218893Sdim/*
2218893Sdim * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
3218893Sdim * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4218893Sdim *
5218893Sdim * This code is free software; you can redistribute it and/or modify it
6234353Sdim * under the terms of the GNU General Public License version 2 only, as
7218893Sdim * published by the Free Software Foundation.
8218893Sdim *
9218893Sdim * This code is distributed in the hope that it will be useful, but WITHOUT
10218893Sdim * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11218893Sdim * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12226633Sdim * version 2 for more details (a copy is included in the LICENSE file that
13221345Sdim * accompanied this code).
14218893Sdim *
15218893Sdim * You should have received a copy of the GNU General Public License version
16226633Sdim * 2 along with this work; if not, write to the Free Software Foundation,
17218893Sdim * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18218893Sdim *
19218893Sdim * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20221345Sdim * or visit www.oracle.com if you need additional information or have any
21226633Sdim * questions.
22226633Sdim */
23226633Sdim
24226633Sdim/**
25234353Sdim *  @test
26218893Sdim *  @bug 4870984
27218893Sdim *  @summary  JPDA: Add support for RFE 4856541 - varargs
28218893Sdim *
29218893Sdim *  @author jjh
30218893Sdim *
31226633Sdim *  @run build TestScaffold VMConnection TargetListener TargetAdapter
32218893Sdim *  @run compile -g VarargsTest.java
33218893Sdim *  @run driver VarargsTest
34218893Sdim */
35218893Sdimimport com.sun.jdi.*;
36218893Sdimimport com.sun.jdi.event.*;
37218893Sdimimport com.sun.jdi.request.*;
38218893Sdim
39234353Sdimimport java.util.*;
40218893Sdim
41218893Sdim    /********** target program **********/
42218893Sdim
43218893Sdimclass VarargsTarg {
44218893Sdim
45218893Sdim    // These are args that will get passed
46218893Sdim    static String[] strArray = new String[] {"a", "b"};
47218893Sdim    static int[] intArray = new int[] {1, 2};
48218893Sdim
49218893Sdim    // We will pass these to a varargs instance method
50    static VarargsTarg vt1 = new VarargsTarg("vt1", "");
51    static VarargsTarg vt2 = new VarargsTarg("vt2", "");
52
53    String iname;
54
55    VarargsTarg(String ... name) {
56        iname = "";
57        for (int ii = 0; ii < name.length; ii++) {
58            iname += name[ii];
59        }
60    }
61
62    public static void main(String[] args){
63        System.out.println("Howdy!");
64        /*
65         * This isn't really part of the test, it just shows
66         * the kinds of calls the debugger test will do and lets
67         * you verify how javac handles these calls.
68         */
69        System.out.println("debuggee: " + varString());
70        System.out.println("debuggee: " + varString(null));
71        System.out.println("debuggee: " + varString("a"));
72        System.out.println("debuggee: " + varString("b", "c"));
73        System.out.println("debuggee: " + fixedString(null));
74        System.out.println("debuggee: " + vt1.varStringInstance(vt1, vt2));
75        System.out.println("debuggge: " + varInt(1, 2, 3));
76        System.out.println("debuggee: " + varInteger( new Integer(89)));
77
78        // Should be autoboxed: javac converts the ints to Integers
79        // Needs a new method in java.lang.Integer which is only
80        // in the generics workspace.
81        System.out.println("debugggee: " + varInteger(3, 5, 6));
82
83        System.out.println("Goodbye from VarargsTarg!");
84        bkpt();
85    }
86    static void bkpt() {
87    }
88
89    /*
90     * Define the methods to be called from the debugger
91     */
92    static String fixedInt(int p1) {
93        return "" + p1;
94    }
95
96    static String fixedInteger(Integer p1) {
97        return "" + p1;
98    }
99
100     static String varInt(int... ss) {
101         String retVal = "";
102         for (int ii = 0; ii < ss.length; ii++) {
103             retVal += ss[ii];
104         }
105         return retVal;
106     }
107
108    static String varInteger(Integer... ss) {
109        String retVal = "";
110        for (int ii = 0; ii < ss.length; ii++) {
111            retVal += ss[ii];
112        }
113        return retVal;
114    }
115
116    static String varString(String... ss) {
117        if (ss == null) {
118            return "-null-";
119        }
120
121        String retVal = "";
122        for (int ii = 0; ii < ss.length; ii++) {
123            retVal += ss[ii];
124        }
125        return retVal;
126    }
127
128    static String varString2(int p1, String... ss) {
129        return p1 + varString(ss);
130    }
131
132    static String fixedString(String ss) {
133        return "-fixed-";
134    }
135
136    String varStringInstance(VarargsTarg... args) {
137        if (args == null) {
138            return "-null-";
139        }
140        //System.out.println("debugee: ss length = " + ss.length);
141        String retVal = iname + ": ";
142        for (int ii = 0; ii < args.length; ii++) {
143            retVal += args[ii].iname;
144        }
145        return retVal;
146    }
147
148}
149
150    /********** test program **********/
151
152public class VarargsTest extends TestScaffold {
153    ClassType targetClass;
154    ThreadReference mainThread;
155
156    VarargsTest (String args[]) {
157        super(args);
158    }
159
160    public static void main(String[] args)      throws Exception {
161        new VarargsTest(args).startTests();
162    }
163
164    void fail(String reason) {
165        failure(reason);
166    }
167
168    /*
169     * Call a method in the debuggee and verify the return value.
170     */
171    void doInvoke(Object ct, Method mm, List args, Object expected) {
172        StringReference returnValue = null;
173        try {
174            returnValue = doInvokeNoVerify(ct, mm, args);
175        } catch (Exception ee) {
176            fail("failure: invokeMethod got exception : " + ee);
177            ee.printStackTrace();
178            return;
179        }
180        if (!returnValue.value().equals(expected)) {
181            fail("failure: expected \"" + expected + "\", got \"" +
182                 returnValue.value() + "\"");
183        }
184    }
185
186    /*
187     * Call a method in the debuggee.
188     */
189    StringReference doInvokeNoVerify(Object ct, Method mm, List args)
190        throws Exception {
191        StringReference returnValue = null;
192        if (ct instanceof ClassType) {
193            returnValue = (StringReference)((ClassType)ct).
194                invokeMethod(mainThread, mm, args, 0);
195        } else {
196            returnValue = (StringReference)((ObjectReference)ct).
197                invokeMethod(mainThread, mm, args, 0);
198        }
199        return returnValue;
200    }
201
202    /********** test core **********/
203
204    protected void runTests() throws Exception {
205        /*
206         * Get to the top of main()
207         * to determine targetClass and mainThread
208         */
209        BreakpointEvent bpe = startToMain("VarargsTarg");
210        targetClass = (ClassType)bpe.location().declaringType();
211        mainThread = bpe.thread();
212
213        /*
214         * Run past the calls the debuggee makes
215         * just to see what they do.
216         */
217        bpe = resumeTo("VarargsTarg", "bkpt", "()V");
218
219        /*
220         * Find Method objects for varString and varString2
221         * Both are tested just to show that the code works
222         * if there is just one param or if there is more than one.
223         */
224        ReferenceType rt = findReferenceType("VarargsTarg");
225
226        List mList;
227
228        /*
229         * The test consists of calling the varargs static and instance methods
230         * (and constructor) passing primitives, Strings, and Objects, and also
231         * passing arrays of the above instead of individual args.
232         * The same code is used in the underlying JDI implementations
233         * for calling instance methods, static methods, and constructors
234         * so this test doesn't have to try all possible argument configurations
235         * with each type of method.
236         */
237
238        mList = rt.methodsByName("varString");
239        Method varString = (Method)mList.get(0);
240
241        mList = rt.methodsByName("varString2");
242        Method varString2 = (Method)mList.get(0);
243
244        if (!varString.isVarArgs()) {
245            fail("failure: varString is not flagged as being var args");
246        }
247        if (!varString2.isVarArgs()) {
248            fail("failure: varString2 is not flagged as being var args");
249        }
250
251        /*
252         * Setup arg lists for both varString and varString2 that
253         * have null in the varargs position.
254         */
255
256        {
257            // call varString()
258            ArrayList nullArg1 = new ArrayList(0);
259            doInvoke(targetClass, varString, nullArg1,  "");
260        }
261        {
262            // call varString(null)
263            ArrayList nullArg1 = new ArrayList(1);
264            nullArg1.add(null);
265            doInvoke(targetClass, varString, nullArg1,  "-null-");
266        }
267        {
268            // call varString(9)
269            ArrayList nullArg2 = new ArrayList(1);
270            nullArg2.add(vm().mirrorOf(9));
271            doInvoke(targetClass, varString2, nullArg2,  "9");
272        }
273        {
274            // call varString(9, null)
275            ArrayList nullArg2 = new ArrayList(2);
276            nullArg2.add(vm().mirrorOf(9));
277            nullArg2.add(null);
278            doInvoke(targetClass, varString2, nullArg2,  "9-null-");
279        }
280        {
281            ArrayList args1 = new ArrayList(4);
282            args1.add(vm().mirrorOf("1"));
283
284            // call varString("1")
285            doInvoke(targetClass, varString, args1, "1");
286
287            // call varString("1", "2")
288            args1.add(vm().mirrorOf("2"));
289            args1.add(vm().mirrorOf("3"));
290            args1.add(vm().mirrorOf("4"));
291            doInvoke(targetClass, varString, args1, "1234");
292        }
293        {
294            ArrayList args2 = new ArrayList(2);
295            args2.add(vm().mirrorOf(9));
296            args2.add(vm().mirrorOf("1"));
297
298            // call varString2(9, "1");
299            doInvoke(targetClass, varString2, args2, "91");
300
301            // call varString2(9, "1", "2");
302            args2.add(vm().mirrorOf("2"));
303            doInvoke(targetClass, varString2, args2, "912");
304        }
305
306        {
307            /*
308             * Passing an array of Strings should work too.
309             */
310            Field ff = targetClass.fieldByName("strArray");
311            Value vv1 = targetClass.getValue(ff);
312
313            // call varString(new String[] {"a", "b"})
314            ArrayList argsArray = new ArrayList(1);
315            argsArray.add(vv1);
316            doInvoke(targetClass, varString, argsArray, "ab");
317
318            /*
319             * But passing an array of Strings and another String
320             * should fail
321             */
322            argsArray.add(vm().mirrorOf("x"));
323            boolean isOk = false;
324            try {
325                // call varString(new String[] {"a", "b"}, "x")
326                doInvokeNoVerify(targetClass, varString, argsArray);
327            } catch (Exception ee) {
328                /*
329                 * Since the number of args passed is > than
330                 * the number of params, JDI assumes they are var args
331                 * and tries to put the array containing the "a" and
332                 * "be" elements into a the first element of an array
333                 * of Strings.  This fails because you can't store
334                 * an array into a String
335                 */
336                isOk = true;
337                //ee.printStackTrace();
338            }
339            if (!isOk) {
340                fail("failure: an array and a String didn't cause an exception");
341            }
342        }
343
344        {
345            /*
346             * Test calling instance method instead of static method,
347             * and passing non-String objects
348             */
349            Field vtField = targetClass.fieldByName("vt1");
350            Value vv1 = targetClass.getValue(vtField);
351
352            vtField = targetClass.fieldByName("vt2");
353            Value vv2 = targetClass.getValue(vtField);
354
355            /* Create a new instance by calling the varargs
356             * ctor.
357             * call new VarargsTarg("vt3", "xx");
358             */
359            Value vv3;
360            {
361                mList = rt.methodsByName("<init>");
362                Method ctor = (Method)mList.get(0);
363                if (!ctor.isVarArgs()) {
364                    fail("failure: Constructor is not varargs");
365                }
366                ArrayList argsArray = new ArrayList(2);
367                argsArray.add(vm().mirrorOf("vt3"));
368                argsArray.add(vm().mirrorOf("xx"));
369                vv3 = targetClass.newInstance(mainThread, ctor, argsArray, 0);
370            }
371            // call vt1.varStringInstance(vv1, vv2, vv3)
372            mList = rt.methodsByName("varStringInstance");
373            Method varStringInstance = (Method)mList.get(0);
374
375            ArrayList argsArray = new ArrayList(3);
376            argsArray.add(vv1);
377            argsArray.add(vv2);
378            argsArray.add(vv3);
379            doInvoke(vv1, varStringInstance, argsArray, "vt1: vt1vt2vt3xx");
380        }
381        {
382            /*
383             * tests with primitive types
384             */
385            List mlist;
386            Method mm;
387            ArrayList ll = new ArrayList(2);
388
389            // call fixedInt(21)
390            mlist = rt.methodsByName("fixedInt");
391            mm = (Method)mlist.get(0);
392            ll.add(vm().mirrorOf(21));
393            doInvoke(targetClass, mm, ll, "21");
394
395            // autoboxing is not implemented in JDI.
396            // call fixedInteger(21)
397            //mlist = rt.methodsByName("fixedInteger");
398            //mm = (Method)mlist.get(0);
399            //doInvoke(targetClass, mm, ll, "21");
400
401            mlist = rt.methodsByName("varInt");
402            mm = (Method)mlist.get(0);
403
404            // call varInt( new int[] {1, 2});
405            Field ff = targetClass.fieldByName("intArray");
406            Value vv1 = targetClass.getValue(ff);
407            ll.set(0, vv1);
408            doInvoke(targetClass, mm, ll, "12");
409
410            // call varInt(21, 22)
411            ll.set(0, vm().mirrorOf(21));
412            ll.add(vm().mirrorOf(22));
413            doInvoke(targetClass, mm, ll, "2122");
414
415            mlist = rt.methodsByName("varInteger");
416            mm = (Method)mlist.get(0);
417
418            // call varInteger(1, 2)
419            // autoboxing is not implemented.
420            //doInvoke(targetClass, mm, ll, "2122");
421        }
422
423        /*
424         * We don't really need this for the test, but
425         * but without it, we sometimes hit 4728096.
426         */
427        listenUntilVMDisconnect();
428        /*
429         * deal with results of test
430         * if anything has called failure("foo") testFailed will be true
431         */
432        if (!testFailed) {
433            println("VarargsTest: passed");
434        } else {
435            throw new Exception("VarargsTest: failed");
436        }
437    }
438}
439