1 /*
2  * Copyright (c) 2001, 2018, 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.jdwp.Event.CLASS_PREPARE;
25 
26 import java.io.*;
27 
28 import nsk.share.*;
29 import nsk.share.jpda.*;
30 import nsk.share.jdwp.*;
31 
32 /**
33  * Test for JDWP event: CLASS_PREPARE.
34  *
35  * See clsprepare001.README for description of test execution.
36  *
37  * This class represents debugger part of the test.
38  * Test is executed by invoking method runIt().
39  * JDWP event is tested in the method waitForTestedEvent().
40  *
41  * @see #runIt()
42  * @see #waitForTestedEvent()
43  */
44 public class clsprepare001 {
45 
46     // exit status constants
47     static final int JCK_STATUS_BASE = 95;
48     static final int PASSED = 0;
49     static final int FAILED = 2;
50 
51     // package and classes names constants
52     static final String PACKAGE_NAME = "nsk.jdwp.Event.CLASS_PREPARE";
53     static final String TEST_CLASS_NAME = PACKAGE_NAME + "." + "clsprepare001";
54     static final String DEBUGEE_CLASS_NAME = TEST_CLASS_NAME + "a";
55 
56     // tested JDWP event constants
57     static final byte TESTED_EVENT_KIND = JDWP.EventKind.CLASS_PREPARE;
58     static final byte TESTED_EVENT_SUSPEND_POLICY = JDWP.SuspendPolicy.ALL;
59 
60     // name and signature of the tested class
61     static final String TESTED_CLASS_NAME = DEBUGEE_CLASS_NAME + "$" + "TestedClass";
62     static final String TESTED_CLASS_SIGNATURE = "L" + TESTED_CLASS_NAME.replace('.', '/') + ";";
63 
64     // usual scaffold objects
65     ArgumentHandler argumentHandler = null;
66     Log log = null;
67     Binder binder = null;
68     Debugee debugee = null;
69     Transport transport = null;
70     int waitTime = 0;  // minutes
71     long timeout = 0;  // milliseconds
72     boolean dead = false;
73     boolean success = true;
74 
75     // obtained data
76     int eventRequestID = 0;
77 
78     // -------------------------------------------------------------------
79 
80     /**
81      * Start test from command line.
82      */
main(String argv[])83     public static void main(String argv[]) {
84         System.exit(run(argv,System.out) + JCK_STATUS_BASE);
85     }
86 
87     /**
88      * Start test from JCK-compilant environment.
89      */
run(String argv[], PrintStream out)90     public static int run(String argv[], PrintStream out) {
91         return new clsprepare001().runIt(argv, out);
92     }
93 
94     // -------------------------------------------------------------------
95 
96     /**
97      * Perform test execution.
98      */
runIt(String argv[], PrintStream out)99     public int runIt(String argv[], PrintStream out) {
100 
101         // make log for debugger messages
102         argumentHandler = new ArgumentHandler(argv);
103         log = new Log(out, argumentHandler);
104         waitTime = argumentHandler.getWaitTime();
105         timeout = waitTime * 60 * 1000;
106 
107         // execute test and display results
108         try {
109             log.display("\n>>> Starting debugee \n");
110 
111             // launch debuggee
112             binder = new Binder(argumentHandler, log);
113             log.display("Launching debugee");
114             debugee = binder.bindToDebugee(DEBUGEE_CLASS_NAME);
115             transport = debugee.getTransport();
116             log.display("  ... debugee launched");
117             log.display("");
118 
119             // set timeout for debuggee responces
120             log.display("Setting timeout for debuggee responces: " + waitTime + " minute(s)");
121             transport.setReadTimeout(timeout);
122             log.display("  ... timeout set");
123 
124             // wait for debuggee started
125             log.display("Waiting for VM_INIT event");
126             debugee.waitForVMInit();
127             log.display("  ... VM_INIT event received");
128 
129             // query debugee for VM-dependent ID sizes
130             log.display("Querying for IDSizes");
131             debugee.queryForIDSizes();
132             log.display("  ... size of VM-dependent types adjusted");
133 
134             // make request for CLASS_PREPARE event
135             log.display("\n>>> Making request for tested event \n");
136 
137             log.display("Making request for CLASS_PREPARE event for class:\n\t"
138                     + TESTED_CLASS_NAME);
139             requestTestedEvent();
140             log.display("  ... got requestID: " + eventRequestID);
141 
142             // resume debuggee
143             log.display("Resumindg debuggee");
144             debugee.resume();
145             log.display("  ... debuggee resumed");
146 
147             // wait for tested CLASS_PREPARE event
148             log.display("\n>>> Testing JDWP event \n");
149             waitForTestedEvent();
150 
151             // clear tested request for CLASS_PREPARE event
152             log.display("\n>>> Clearing request for tested event \n");
153             clearTestedRequest();
154 
155             // finish debuggee after testing
156             log.display("\n>>> Finishing debuggee \n");
157 
158             // resume debuggee
159             log.display("Resuming debuggee");
160             debugee.resume();
161             log.display("  ... debuggee resumed");
162 
163             // wait for debuggee exited
164             log.display("Waiting for VM_DEATH event");
165             debugee.waitForVMDeath();
166             dead = true;
167             log.display("  ... VM_DEATH event received");
168 
169         } catch (Failure e) {
170             log.complain("TEST FAILED: " + e.getMessage());
171             success = false;
172         } catch (Exception e) {
173             e.printStackTrace(out);
174             log.complain("Caught unexpected exception while running the test:\n\t" + e);
175             success = false;
176         } finally {
177             // quit debugee
178             log.display("\n>>> Finishing test \n");
179             quitDebugee();
180         }
181 
182         // check test results
183         if (!success) {
184             log.complain("TEST FAILED");
185             return FAILED;
186         }
187 
188         out.println("TEST PASSED");
189         return PASSED;
190 
191     }
192 
193     /**
194      * Make request for tested CLASS_PREPARE event.
195      */
requestTestedEvent()196     void requestTestedEvent() {
197         Failure failure = new Failure("Error occured while makind request for tested event");
198 
199         // create command packet and fill requred out data
200         log.display("Create command packet: " + "EventRequest.Set");
201         CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Set);
202         log.display("    eventKind: " + TESTED_EVENT_KIND);
203         command.addByte(TESTED_EVENT_KIND);
204         log.display("    eventPolicy: " + TESTED_EVENT_SUSPEND_POLICY);
205         command.addByte(TESTED_EVENT_SUSPEND_POLICY);
206         log.display("    modifiers: " + 1);
207         command.addInt(1);
208         log.display("      modKind: " + JDWP.EventModifierKind.CLASS_MATCH);
209         command.addByte(JDWP.EventModifierKind.CLASS_MATCH);
210         log.display("      classPattern: " + TESTED_CLASS_NAME);
211         command.addString(TESTED_CLASS_NAME);
212         command.setLength();
213         log.display("  ... command packet composed");
214 
215         // send command packet to debugee
216         try {
217             log.display("Sending command packet:\n" + command);
218             transport.write(command);
219             log.display("  ... command packet sent");
220         } catch (IOException e) {
221             log.complain("Unable to send command packet:\n\t" + e);
222             success = false;
223             throw failure;
224         }
225 
226         ReplyPacket reply = new ReplyPacket();
227 
228         // receive reply packet from debugee
229         try {
230             log.display("Waiting for reply packet");
231             transport.read(reply);
232             log.display("  ... packet received:\n" + reply);
233         } catch (IOException e) {
234             log.complain("Unable to read reply packet:\n\t" + e);
235             success = false;
236             throw failure;
237         }
238 
239         // check reply packet header
240         try{
241             log.display("Checking header of reply packet");
242             reply.checkHeader(command.getPacketID());
243             log.display("  .. packet header is correct");
244         } catch (BoundException e) {
245             log.complain("Bad header of reply packet:\n\t" + e.getMessage());
246             success = false;
247             throw failure;
248         }
249 
250         // start parsing reply packet data
251         log.display("Parsing reply packet:");
252         reply.resetPosition();
253 
254         // extract requestID
255         int requestID = 0;
256         try {
257             requestID = reply.getInt();
258             log.display("    requestID: " + requestID);
259         } catch (BoundException e) {
260             log.complain("Unable to extract requestID from request reply packet:\n\t"
261                         + e.getMessage());
262             success = false;
263             throw failure;
264         }
265 
266         // check requestID
267         if (requestID == 0) {
268             log.complain("Unexpected null requestID returned: " + requestID);
269             success = false;
270             throw failure;
271         }
272 
273         eventRequestID = requestID;
274 
275         // check for extra data in reply packet
276         if (!reply.isParsed()) {
277             log.complain("Extra trailing bytes found in request reply packet at: "
278                         + reply.offsetString());
279             success = false;
280         }
281 
282         log.display("  ... reply packet parsed");
283     }
284 
285     /**
286      * Clear request for tested CLASS_PREPARE event.
287      */
clearTestedRequest()288     void clearTestedRequest() {
289         Failure failure = new Failure("Error occured while clearing request for tested event");
290 
291         // create command packet and fill requred out data
292         log.display("Create command packet: " + "EventRequest.Clear");
293         CommandPacket command = new CommandPacket(JDWP.Command.EventRequest.Clear);
294         log.display("    event: " + TESTED_EVENT_KIND);
295         command.addByte(TESTED_EVENT_KIND);
296         log.display("    requestID: " + eventRequestID);
297         command.addInt(eventRequestID);
298         log.display("  ... command packet composed");
299 
300         // send command packet to debugee
301         try {
302             log.display("Sending command packet:\n" + command);
303             transport.write(command);
304             log.display("  ... command packet sent");
305         } catch (IOException e) {
306             log.complain("Unable to send command packet:\n\t" + e);
307             success = false;
308             throw failure;
309         }
310 
311         ReplyPacket reply = new ReplyPacket();
312 
313         // receive reply packet from debugee
314         try {
315             log.display("Waiting for reply packet");
316             transport.read(reply);
317             log.display("  ... packet received:\n" + reply);
318         } catch (IOException e) {
319             log.complain("Unable to read reply packet:\n\t" + e);
320             success = false;
321             throw failure;
322         }
323 
324         // check reply packet header
325         try{
326             log.display("Checking header of reply packet");
327             reply.checkHeader(command.getPacketID());
328             log.display("  .. packet header is correct");
329         } catch (BoundException e) {
330             log.complain("Bad header of reply packet:\n\t" + e.getMessage());
331             success = false;
332             throw failure;
333         }
334 
335         // start parsing reply packet data
336         log.display("Parsing reply packet:");
337         reply.resetPosition();
338 
339         log.display("    no data");
340 
341         // check for extra data in reply packet
342         if (!reply.isParsed()) {
343             log.complain("Extra trailing bytes found in request reply packet at: "
344                         + reply.offsetString());
345             success = false;
346         }
347 
348         log.display("  ... reply packet parsed");
349     }
350 
351     /**
352      * Wait for tested CLASS_PREPARE event.
353      */
waitForTestedEvent()354     void waitForTestedEvent() {
355 
356         EventPacket eventPacket = null;
357 
358         // receive reply packet from debugee
359         try {
360             log.display("Waiting for event packet (for " + timeout + "ms timeout)");
361             eventPacket = debugee.getEventPacket(timeout);
362             log.display("  ... event packet received:\n" + eventPacket);
363         } catch (IOException e) {
364             log.complain("Unable to read tested event packet:\n\t" + e);
365             success = false;
366             return;
367         }
368 
369         // check reply packet header
370         try{
371             log.display("Checking header of event packet");
372             eventPacket.checkHeader();
373             log.display("  ... packet header is correct");
374         } catch (BoundException e) {
375             log.complain("Bad header of tested event packet:\n\t"
376                         + e.getMessage());
377             success = false;
378             return;
379         }
380 
381         // start parsing reply packet data
382         log.display("Parsing event packet:");
383         eventPacket.resetPosition();
384 
385         // get suspendPolicy value
386         byte suspendPolicy = 0;
387         try {
388             suspendPolicy = eventPacket.getByte();
389             log.display("    suspendPolicy: " + suspendPolicy);
390         } catch (BoundException e) {
391             log.complain("Unable to get suspendPolicy value from tested event packet:\n\t"
392                         + e.getMessage());
393             success = false;
394             return;
395         }
396 
397         // check suspendPolicy value
398         if (suspendPolicy != TESTED_EVENT_SUSPEND_POLICY) {
399             log.complain("Unexpected SuspendPolicy in tested event packet: " +
400                         suspendPolicy + " (expected: " + TESTED_EVENT_SUSPEND_POLICY + ")");
401             success = false;
402         }
403 
404         // get events count
405         int events = 0;
406         try {
407             events = eventPacket.getInt();
408             log.display("    events: " + events);
409         } catch (BoundException e) {
410             log.complain("Unable to get events count from tested event packet:\n\t"
411                         + e.getMessage());
412             success = false;
413             return;
414         }
415 
416         // check events count
417         if (events < 0) {
418             log.complain("Negative value of events number in tested event packet: " +
419                         events + " (expected: " + 1 + ")");
420             success = false;
421         } else if (events != 1) {
422             log.complain("Invalid number of events in tested event packet: " +
423                         events + " (expected: " + 1 + ")");
424             success = false;
425         }
426 
427         // extract each event
428         for (int i = 0; i < events; i++) {
429             log.display("    event #" + i + ":");
430 
431             // get eventKind
432             byte eventKind = 0;
433             try {
434                 eventKind = eventPacket.getByte();
435                 log.display("      eventKind: " + eventKind);
436             } catch (BoundException e) {
437                 log.complain("Unable to get eventKind of event #" + i + " from tested event packet:\n\t"
438                             + e.getMessage());
439                 success = false;
440                 return;
441             }
442 
443             // check eventKind
444             if (eventKind != JDWP.EventKind.CLASS_PREPARE) {
445                 log.complain("Unexpected eventKind of event " + i + " in tested event packet: " +
446                             eventKind + " (expected: " + JDWP.EventKind.CLASS_PREPARE + ")");
447                 success = false;
448                 return;
449             }
450 
451             // get requestID
452             int requestID = 0;
453             try {
454                 requestID = eventPacket.getInt();
455                 log.display("      requestID: " + requestID);
456             } catch (BoundException e) {
457                 log.complain("Unable to get requestID of event #" + i + " from tested event packet:\n\t"
458                             + e.getMessage());
459                 success = false;
460                 return;
461             }
462 
463             // check requestID
464             if (requestID != eventRequestID) {
465                 log.complain("Unexpected requestID of event " + i + " in tested event packet: " +
466                             requestID + " (expected: " + eventRequestID + ")");
467                 success = false;
468             }
469 
470             // get threadID
471             long threadID = 0;
472             try {
473                 threadID = eventPacket.getObjectID();
474                 log.display("      threadID: " + threadID);
475             } catch (BoundException e) {
476                 log.complain("Unable to get threadID of event #" + i + " from tested event packet:\n\t"
477                             + e.getMessage());
478                 success = false;
479                 return;
480             }
481 
482             // check threadID
483             if (threadID == 0) {
484                 log.complain("Unexpected null threadID of event " + i + " in tested event packet: " +
485                             threadID);
486                 success = false;
487             }
488 
489             // get refTypeTag
490             byte refTypeTag = 0;
491             try {
492                 refTypeTag = eventPacket.getByte();
493                 log.display("      refTypeTag: " + refTypeTag);
494             } catch (BoundException e) {
495                 log.complain("Unable to get refTypeTag of event #" + i + " from tested event packet:\n\t"
496                             + e.getMessage());
497                 success = false;
498                 return;
499             }
500 
501             // check refTypeGag
502             if (refTypeTag != JDWP.TypeTag.CLASS) {
503                 log.complain("Unexpected refTypeTag of event " + i + " in tested event packet: " +
504                             refTypeTag + " (expected: " + JDWP.TypeTag.CLASS + ")");
505                 success = false;
506             }
507 
508             // get referenceTypeID
509             long referenceTypeID = 0;
510             try {
511                 referenceTypeID = eventPacket.getReferenceTypeID();
512                 log.display("      referenceTypeID: " + referenceTypeID);
513             } catch (BoundException e) {
514                 log.complain("Unable to get referenceTypeID of event #" + i + " from tested event packet:\n\t"
515                             + e.getMessage());
516                 success = false;
517                 return;
518             }
519 
520             // check referenceTypeID
521             if (referenceTypeID == 0) {
522                 log.complain("Unexpected null referenceTypeID of event " + i + " in tested event packet: " +
523                             referenceTypeID);
524                 success = false;
525             }
526 
527             // get signature
528             String signature = null;
529             try {
530                 signature = eventPacket.getString();
531                 log.display("      signature: " + signature);
532             } catch (BoundException e) {
533                 log.complain("Unable to get class signature of event #" + i + " from tested event packet:\n\t"
534                             + e.getMessage());
535                 success = false;
536                 return;
537             }
538 
539             // check signature
540             if (!signature.equals(TESTED_CLASS_SIGNATURE)) {
541                 log.complain("Unexpected class signature of event " + i + " in tested event packet: " +
542                             signature + " (expected: " + TESTED_CLASS_SIGNATURE + ")");
543                 success = false;
544             }
545 
546             // get status
547             int status = 0;
548             try {
549                 status = eventPacket.getInt();
550                 log.display("      status: " + status);
551             } catch (BoundException e) {
552                 log.complain("Unable to get class status of event #" + i + " from tested event packet:\n\t"
553                             + e.getMessage());
554                 success = false;
555                 return;
556             }
557 
558             // check status
559             if ((status & JDWP.ClassStatus.ERROR) != 0) {
560                 log.complain("Unexpected class status of event " + i + " in tested event packet: " +
561                             status + " (expected: w/o bit " + JDWP.ClassStatus.ERROR + ")");
562                 success = false;
563             }
564         }
565 
566         // check for extra data in event packet
567         if (!eventPacket.isParsed()) {
568             log.complain("Extra trailing bytes found in event packet at: "
569                         + eventPacket.offsetString());
570             success = false;
571         }
572 
573         log.display("  ... event packet parsed");
574     }
575 
576     /**
577      * Disconnect debuggee and wait for it exited.
578      */
quitDebugee()579     void quitDebugee() {
580         if (debugee == null)
581             return;
582 
583         // disconnect debugee
584         if (!dead) {
585             try {
586                 log.display("Disconnecting debuggee");
587                 debugee.dispose();
588                 log.display("  ... debuggee disconnected");
589             } catch (Failure e) {
590                 log.display("Failed to finally disconnect debuggee:\n\t"
591                             + e.getMessage());
592             }
593         }
594 
595         // wait for debugee exited
596         log.display("Waiting for debuggee exit");
597         int code = debugee.waitFor();
598         log.display("  ... debuggee exited with exit code: " + code);
599 
600         // analize debugee exit status code
601         if (code != JCK_STATUS_BASE + PASSED) {
602             log.complain("Debuggee FAILED with exit code: " + code);
603             success = false;
604         }
605     }
606 
607 }
608