1 /*
2  * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 package nsk.jdi.ClassType.newInstance;
25 
26 import nsk.share.*;
27 import nsk.share.jpda.*;
28 import nsk.share.jdi.*;
29 
30 import com.sun.jdi.*;
31 import java.util.*;
32 import java.io.*;
33 
34 import com.sun.jdi.event.*;
35 import com.sun.jdi.request.*;
36 
37 /**
38  * The test for the implementation of an object of the type     <BR>
39  * ClassType.                                                   <BR>
40  *                                                              <BR>
41  * The test checks up that results of the method                <BR>
42  * <code>com.sun.jdi.ClassType.newInstance()</code>             <BR>
43  * complies with its specification.                             <BR>
44  * The case for testing includes invoking the method to create  <BR>
45  * new instance of the class TestClass                          <BR>
46  * which is global to a class implementing debuggee's thread    <BR>
47  * in which instance creation is performed.                     <BR>
48  * No exception is expected to be thrown in response to call    <BR>
49  * to the method.                                               <BR>
50  * <BR>
51  * The test works as follows.                                   <BR>
52  * A debugger launchs a debuggee which creates new thread, thread2. <BR>
53  * The tested class TestClass is specified outside of the class <BR>
54  *      Threadnewinstance002a extends Thread                    <BR>
55  * After getting thread2 running but locked at a monitor        <BR>
56  * the debugger informs the debugger of the thread2 creation    <BR>
57  * and waits for an instruction from it.                        <BR>
58  * Upon receiving the message from the debuggee, the debugger   <BR>
59  * sets up a breakpoint for the thread2 and instructs the       <BR>
60  * debuggee to unlock the thread2 and after getting it suspended<BR>
61  * at the breakpoint, prepares arguments and invokes the method.<BR>
62  * After the method completes, the debugger checks up on        <BR>
63  * a returned ObjectReference value;                            <BR>
64  * the following  is expected to be true:                       <BR>
65  *     objRef.referenceType().equals(classType)                 <BR>
66  * where                                                        <BR>
67  *     ObjectReference objRef - is returned value               <BR>
68  *     ClassType classType    - is a mirror of the tested class.<BR>
69  */
70 
71 public class newinstance001 {
72 
73     //----------------------------------------------------- templete section
74     static final int PASSED = 0;
75     static final int FAILED = 2;
76     static final int PASS_BASE = 95;
77 
78     //----------------------------------------------------- templete parameters
79     static final String
80     sHeader1 = "\n==> nsk/jdi/ClassType/newInstance/newinstance001  ",
81     sHeader2 = "--> debugger: ",
82     sHeader3 = "##> debugger: ";
83 
84     //----------------------------------------------------- main method
85 
main(String argv[])86     public static void main (String argv[]) {
87         int result = run(argv, System.out);
88         System.exit(result + PASS_BASE);
89     }
90 
run(String argv[], PrintStream out)91     public static int run (String argv[], PrintStream out) {
92         return new newinstance001().runThis(argv, out);
93     }
94 
95     //--------------------------------------------------   log procedures
96 
97     private static Log  logHandler;
98 
log1(String message)99     private static void log1(String message) {
100         logHandler.display(sHeader1 + message);
101     }
log2(String message)102     private static void log2(String message) {
103         logHandler.display(sHeader2 + message);
104     }
log3(String message)105     private static void log3(String message) {
106         logHandler.complain(sHeader3 + message);
107     }
108 
109     //  ************************************************    test parameters
110 
111     private String debuggeeName =
112         "nsk.jdi.ClassType.newInstance.newinstance001a";
113 
114     private String testedClassName =
115         "nsk.jdi.ClassType.newInstance.TestClass";
116 
117     private String threadName = "testedThread";
118 
119     private String threadClassName =
120         "nsk.jdi.ClassType.newInstance.Threadnewinstance001a";
121 
122     //String mName = "nsk.jdi.ClassType.newInstance";
123 
124     //====================================================== test program
125     //------------------------------------------------------ common section
126 
127     static ArgumentHandler      argsHandler;
128 
129     static int waitTime;
130 
131     static VirtualMachine      vm            = null;
132     static EventRequestManager eventRManager = null;
133     static EventQueue          eventQueue    = null;
134     static EventSet            eventSet      = null;
135 
136     ReferenceType     testedClass  = null;
137 
138     ReferenceType     threadClass  = null;
139 
140     ThreadReference   thread2      = null;
141     ThreadReference   mainThread   = null;
142 
143     static int  testExitCode = PASSED;
144 
145     static final int returnCode0 = 0;
146     static final int returnCode1 = 1;
147     static final int returnCode2 = 2;
148     static final int returnCode3 = 3;
149     static final int returnCode4 = 4;
150 
151     //------------------------------------------------------ methods
152 
runThis(String argv[], PrintStream out)153     private int runThis (String argv[], PrintStream out) {
154 
155         Debugee debuggee;
156 
157         argsHandler     = new ArgumentHandler(argv);
158         logHandler      = new Log(out, argsHandler);
159         Binder binder   = new Binder(argsHandler, logHandler);
160 
161         if (argsHandler.verbose()) {
162             debuggee = binder.bindToDebugee(debuggeeName + " -vbs");
163         } else {
164             debuggee = binder.bindToDebugee(debuggeeName);
165         }
166 
167         waitTime = argsHandler.getWaitTime();
168 
169 
170         IOPipe pipe     = new IOPipe(debuggee);
171 
172         debuggee.redirectStderr(out);
173         log2(debuggeeName + " debuggee launched");
174         debuggee.resume();
175 
176         String line = pipe.readln();
177         if ((line == null) || !line.equals("ready")) {
178             log3("signal received is not 'ready' but: " + line);
179             return FAILED;
180         } else {
181             log2("'ready' recieved");
182         }
183 
184         vm = debuggee.VM();
185 
186     //------------------------------------------------------  testing section
187         log1("      TESTING BEGINS");
188 
189         for (int i = 0; ; i++) {
190 
191             pipe.println("newcheck");
192             line = pipe.readln();
193 
194             if (line.equals("checkend")) {
195                 log2("     : returned string is 'checkend'");
196                 break ;
197             } else if (!line.equals("checkready")) {
198                 log3("ERROR: returned string is not 'checkready'");
199                 testExitCode = FAILED;
200                 break ;
201             }
202 
203             log1("new checkready: #" + i);
204 
205             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ variable part
206 
207             int expresult = returnCode0;
208 
209 
210             eventRManager = vm.eventRequestManager();
211             eventQueue    = vm.eventQueue();
212 
213             String breakpointMethod1 = "runt1";
214 
215             String bpLine1 = "breakpointLineNumber1";
216 
217             List            allThreads   = null;
218             ListIterator    listIterator = null;
219             List            classes      = null;
220 
221             BreakpointRequest breakpRequest1 = null;
222 
223             ClassType classType    = null;
224 
225             label0: {
226 
227                 log2("getting ThreadReference object");
228                 try {
229                     allThreads  = vm.allThreads();
230                     classes     = vm.classesByName(threadClassName);
231                     threadClass = (ReferenceType) classes.get(0);
232                 } catch ( Exception e) {
233                     log3("ERROR: Exception at very beginning !? : " + e);
234                     expresult = returnCode1;
235                     break label0;
236                 }
237 
238 
239                 log2("......getting Thread thread2 - 1-st argument");
240                 listIterator = allThreads.listIterator();
241                 for (;;) {
242                     try {
243                         thread2 = (ThreadReference) listIterator.next();
244                         if (thread2.name().equals(threadName))
245                             break ;
246                     } catch ( NoSuchElementException e ) {
247                         log3("ERROR: NoSuchElementException for listIterator.next()");
248                         log3("ERROR: NO THREAD2 ?????????!!!!!!!");
249                         expresult = returnCode1;
250                         break label0;
251                     }
252                 }
253 
254                 log2("setting up a breakpoint");
255 
256                 breakpRequest1 = settingBreakpoint(breakpointMethod1, bpLine1, "one");
257                 if (breakpRequest1 == null) {
258                     expresult = returnCode1;
259                     break label0;
260                 }
261             }
262 
263             label1: {
264 
265                 if (expresult != returnCode0)
266                        break label1;
267 
268                 log2("     enabling breakpRequest1");
269                 breakpRequest1.enable();
270 
271                 log2("       forcing the main thread to leave synchronized block");
272                 pipe.println("continue");
273                 line = pipe.readln();
274                 if (!line.equals("docontinue")) {
275                     log3("ERROR: returned string is not 'docontinue'");
276                     expresult = returnCode4;
277                     break label1;
278                 }
279 
280                 log2("      getting BreakpointEvent");
281                 expresult = breakpoint();
282                 if (expresult != returnCode0)
283                     break label1;
284                 log2("      thread2 is at breakpoint");
285 
286 
287                 log2("......getting ClassType classType - an object to apply newInstance()");
288                 classes     = vm.classesByName(testedClassName);
289                 testedClass = (ReferenceType) classes.get(0);
290                 classType   = (ClassType) testedClass;
291 
292                 List         invokeMethods = testedClass.methods();
293                 ListIterator            li = invokeMethods.listIterator();
294 
295                 Method       invokeMethod = null;
296 
297                 log2("......getting Method invokeMethod - a constructor to invoke; 2-nd argument");
298                 try {
299                     for (;;) {
300                         invokeMethod = (Method) li.next();
301                         if (!invokeMethod.isConstructor())
302                             continue;
303                         if (invokeMethod.arguments().size() == 0)
304                             break;
305                     }
306                 } catch ( AbsentInformationException e1 ) {
307                     log2("       AbsentInformationException ");
308                     break label1;
309                 } catch ( NoSuchElementException e2 ) {
310                     log3("ERROR: NoSuchElementException ");
311                     expresult = returnCode2;
312                     break label1;
313                 }
314 
315 
316                 // this is only to get an empty List with JDI methods but not with API List methods
317                 log2("......forming an empty List argumentList for 3-d argument");
318                 log2("       List argumentList = testedClass.methodsByName('m');");
319                 List<Method> argumentListm = testedClass.methodsByName("m");
320                 log2("       argumentList.clear();");
321                 argumentListm.clear();
322                 List<? extends Value> argumentList = Collections.emptyList();
323 
324                 ObjectReference objRef = null;
325 
326                 log2("......ObjectReference objRef = classType.newInstance(thread2, invokeMethod, argumentList, 0);");
327                 log2("      No Exception is expected");
328                 try {
329                     objRef = classType.newInstance(thread2,
330                                      invokeMethod, argumentList, 0);
331                     if (objRef == null)
332                         log2("       objRe == null");
333 
334 
335                     log2("        ReferenceType refType = objRef.referenceType();");
336                     ReferenceType refType = objRef.referenceType();
337 
338                     log2("        ClassType cType = (ClassType) refType;");
339                     ClassType cType = (ClassType) refType;
340 
341                     log2("......checking up on: cType.equals(classType); ");
342                     if (!cType.equals(classType)) {
343                         log3("ERROR: !cType.equals(classType)");
344                         expresult = returnCode1;
345                     }
346 
347                 } catch ( Exception e ) {
348                              log3("ERROR: Exception for classType.newInstance() :" + e);
349                              expresult = returnCode1;
350                 }
351             }
352             vm.resume();
353 
354             //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
355             log2("     the end of testing");
356             if (expresult != returnCode0)
357                 testExitCode = FAILED;
358         }
359         log1("      TESTING ENDS");
360 
361     //--------------------------------------------------   test summary section
362     //-------------------------------------------------    standard end section
363 
364         pipe.println("quit");
365         log2("waiting for the debuggee to finish ...");
366         debuggee.waitFor();
367 
368         int status = debuggee.getStatus();
369         if (status != PASSED + PASS_BASE) {
370             log3("debuggee returned UNEXPECTED exit status: " +
371                     status + " != PASS_BASE");
372             testExitCode = FAILED;
373         } else {
374             log2("debuggee returned expected exit status: " +
375                     status + " == PASS_BASE");
376         }
377 
378         if (testExitCode != PASSED) {
379             System.out.println("TEST FAILED");
380         }
381         return testExitCode;
382     }
383 
384 
385    /*
386     * private BreakpointRequest settingBreakpoint(String, String, String)
387     *
388     * It sets up a breakpoint within a given method at given line number
389     * for the thread2 only.
390     * Third parameter is required for any case in future debugging, as if.
391     *
392     * Return codes:
393     *  = BreakpointRequest object  in case of success
394     *  = null   in case of an Exception thrown within the method
395     */
396 
settingBreakpoint( String methodName, String bpLine, String property)397     private BreakpointRequest settingBreakpoint ( String methodName,
398                                                   String bpLine,
399                                                   String property) {
400 
401         log2("setting up a breakpoint: method: '" + methodName + "' line: " + bpLine );
402 
403         List              alllineLocations = null;
404         Location          lineLocation     = null;
405         BreakpointRequest breakpRequest    = null;
406 
407         try {
408 //            Method  method  = (Method) testedclass.methodsByName(methodName).get(0);
409             Method  method  = (Method) threadClass.methodsByName(methodName).get(0);
410 
411             alllineLocations = method.allLineLocations();
412 
413             int n =
414 //                ( (IntegerValue) testedclass.getValue(testedclass.fieldByName(bpLine) ) ).value();
415                 ( (IntegerValue) threadClass.getValue(threadClass.fieldByName(bpLine) ) ).value();
416             if (n > alllineLocations.size()) {
417                 log3("ERROR:  TEST_ERROR_IN_settingBreakpoint(): number is out of bound of method's lines");
418             } else {
419                 lineLocation = (Location) alllineLocations.get(n);
420                 try {
421                     breakpRequest = eventRManager.createBreakpointRequest(lineLocation);
422                     breakpRequest.putProperty("number", property);
423                     breakpRequest.addThreadFilter(thread2);
424                     breakpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD);
425                 } catch ( Exception e1 ) {
426                     log3("ERROR: inner Exception within settingBreakpoint() : " + e1);
427                     breakpRequest    = null;
428                 }
429             }
430         } catch ( Exception e2 ) {
431             log3("ERROR: ATTENTION:  outer Exception within settingBreakpoint() : " + e2);
432             breakpRequest    = null;
433         }
434 
435         if (breakpRequest == null)
436             log2("      A BREAKPOINT HAS NOT BEEN SET UP");
437         else
438             log2("      a breakpoint has been set up");
439 
440         return breakpRequest;
441     }
442 
443 
444     /*
445      * private int breakpoint ()
446      *
447      * It removes events from EventQueue until gets first BreakpointEvent.
448      * To get next EventSet value, it uses the method
449      *    EventQueue.remove(int timeout)
450      * The timeout argument passed to the method, is "waitTime*60000".
451      * Note: the value of waitTime is set up with
452      *       the method ArgumentHandler.getWaitTime() at the beginning of the test.
453      *
454      * Return codes:
455      *  = returnCode0 - success;
456      *  = returnCode2 - Exception when "eventSet = eventQueue.remove()" is executed
457      *  = returnCode3 - default case when loop of processing an event, that is,
458      *                  an unspecified event was taken from the EventQueue
459      */
460 
breakpoint()461     private int breakpoint () {
462 
463         int returnCode = returnCode0;
464 
465         log2("       waiting for BreakpointEvent");
466 
467         labelBP:
468             for (;;) {
469 
470                 log2("       new:  eventSet = eventQueue.remove();");
471                 try {
472                     eventSet = eventQueue.remove(waitTime*60000);
473                     if (eventSet == null) {
474                         log3("ERROR:  timeout for waiting for a BreakpintEvent");
475                         returnCode = returnCode3;
476                         break labelBP;
477                     }
478                 } catch ( Exception e ) {
479                     log3("ERROR: Exception for  eventSet = eventQueue.remove(); : " + e);
480                     returnCode = 1;
481                     break labelBP;
482                 }
483 
484                 if (eventSet != null) {
485 
486                     log2("     :  eventSet != null;  size == " + eventSet.size());
487 
488                     EventIterator eIter = eventSet.eventIterator();
489                     Event         ev    = null;
490 
491                     for (; eIter.hasNext(); ) {
492 
493                         if (returnCode != returnCode0)
494                             break;
495 
496                         ev = eIter.nextEvent();
497 
498                     ll: for (int ifor =0;  ; ifor++) {
499 
500                         try {
501                           switch (ifor) {
502 
503                           case 0:  AccessWatchpointEvent awe = (AccessWatchpointEvent) ev;
504                                    log2("      AccessWatchpointEvent removed");
505                                    break ll;
506                           case 1:  BreakpointEvent be = (BreakpointEvent) ev;
507                                    log2("      BreakpointEvent removed");
508                                    break labelBP;
509                           case 2:  ClassPrepareEvent cpe = (ClassPrepareEvent) ev;
510                                    log2("      ClassPreparEvent removed");
511                                    break ll;
512                           case 3:  ClassUnloadEvent cue = (ClassUnloadEvent) ev;
513                                    log2("      ClassUnloadEvent removed");
514                                    break ll;
515                           case 4:  ExceptionEvent ee = (ExceptionEvent) ev;
516                                    log2("      ExceptionEvent removed");
517                                    break ll;
518                           case 5:  MethodEntryEvent mene = (MethodEntryEvent) ev;
519                                    log2("      MethodEntryEvent removed");
520                                    break ll;
521                           case 6:  MethodExitEvent mexe = (MethodExitEvent) ev;
522                                    log2("      MethodExiEvent removed");
523                                    break ll;
524                           case 7:  ModificationWatchpointEvent mwe = (ModificationWatchpointEvent) ev;
525                                    log2("      ModificationWatchpointEvent removed");
526                                    break ll;
527                           case 8:  StepEvent se = (StepEvent) ev;
528                                    log2("      StepEvent removed");
529                                    break ll;
530                           case 9:  ThreadDeathEvent tde = (ThreadDeathEvent) ev;
531                                    log2("      ThreadDeathEvent removed");
532                                    break ll;
533                           case 10: ThreadStartEvent tse = (ThreadStartEvent) ev;
534                                    log2("      ThreadStartEvent removed");
535                                    break ll;
536                           case 11: VMDeathEvent vmde = (VMDeathEvent) ev;
537                                    log2("      VMDeathEvent removed");
538                                    break ll;
539                           case 12: VMStartEvent vmse = (VMStartEvent) ev;
540                                    log2("      VMStartEvent removed");
541                                    break ll;
542                           case 13: WatchpointEvent we = (WatchpointEvent) ev;
543                                    log2("      WatchpointEvent removed");
544                                    break ll;
545 
546                           default: log3("ERROR:  default case for casting event");
547                                    returnCode = returnCode3;
548                                    break ll;
549                           } // switch
550                         } catch ( ClassCastException e ) {
551                         }   // try
552                     }       // ll: for (int ifor =0;  ; ifor++)
553                 }           // for (; ev.hasNext(); )
554             }
555         }
556         if (returnCode == returnCode0)
557             log2("     :  eventSet == null:  EventQueue is empty");
558 
559         return returnCode;
560     }
561 }
562