RunToExit.java revision 10093:056cd206a147
1/*
2 * Copyright (c) 2004, 2013, 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/* @test
25 * @bug 4997445
26 * @summary Test that with server=y, when VM runs to System.exit() no error happens
27 *
28 * @build VMConnection RunToExit Exit0
29 * @run driver RunToExit
30 */
31import java.io.InputStream;
32import java.io.IOException;
33import java.io.File;
34import java.io.BufferedInputStream;
35import java.net.ServerSocket;
36import com.sun.jdi.Bootstrap;
37import com.sun.jdi.VirtualMachine;
38import com.sun.jdi.event.*;
39import com.sun.jdi.connect.Connector;
40import com.sun.jdi.connect.AttachingConnector;
41import java.util.Map;
42import java.util.List;
43import java.util.Iterator;
44
45public class RunToExit {
46
47    /* Increment this when ERROR: seen */
48    static int error_seen = 0;
49    static volatile boolean ready = false;
50    /*
51     * Helper class to direct process output to a StringBuffer
52     */
53    static class IOHandler implements Runnable {
54        private String              name;
55        private BufferedInputStream in;
56        private StringBuffer        buffer;
57
58        IOHandler(String name, InputStream in) {
59            this.name = name;
60            this.in = new BufferedInputStream(in);
61            this.buffer = new StringBuffer();
62        }
63
64        static void handle(String name, InputStream in) {
65            IOHandler handler = new IOHandler(name, in);
66            Thread thr = new Thread(handler);
67            thr.setDaemon(true);
68            thr.start();
69        }
70
71        public void run() {
72            try {
73                byte b[] = new byte[100];
74                for (;;) {
75                    int n = in.read(b, 0, 100);
76                    // The first thing that will get read is
77                    //    Listening for transport dt_socket at address: xxxxx
78                    // which shows the debuggee is ready to accept connections.
79                    ready = true;
80                    if (n < 0) {
81                        break;
82                    }
83                    buffer.append(new String(b, 0, n));
84                }
85            } catch (IOException ioe) { }
86
87            String str = buffer.toString();
88            if ( str.contains("ERROR:") ) {
89                error_seen++;
90            }
91            System.out.println(name + ": " + str);
92        }
93
94    }
95
96    /*
97     * Find a connector by name
98     */
99    private static Connector findConnector(String name) {
100        List connectors = Bootstrap.virtualMachineManager().allConnectors();
101        Iterator iter = connectors.iterator();
102        while (iter.hasNext()) {
103            Connector connector = (Connector)iter.next();
104            if (connector.name().equals(name)) {
105                return connector;
106            }
107        }
108        return null;
109    }
110
111    /*
112     * Launch a server debuggee with the given address
113     */
114    private static Process launch(String address, String class_name) throws IOException {
115        String exe =   System.getProperty("java.home")
116                     + File.separator + "bin" + File.separator + "java";
117        String cmd = exe + " " + VMConnection.getDebuggeeVMOptions() +
118            " -agentlib:jdwp=transport=dt_socket" +
119            ",server=y" + ",suspend=y" + ",address=" + address +
120            " " + class_name;
121
122        System.out.println("Starting: " + cmd);
123
124        Process p = Runtime.getRuntime().exec(cmd);
125
126        IOHandler.handle("Input Stream", p.getInputStream());
127        IOHandler.handle("Error Stream", p.getErrorStream());
128
129        return p;
130    }
131
132    /*
133     * - pick a TCP port
134     * - Launch a server debuggee: server=y,suspend=y,address=${port}
135     * - run it to VM death
136     * - verify we saw no error
137     */
138    public static void main(String args[]) throws Exception {
139        // find a free port
140        ServerSocket ss = new ServerSocket(0);
141        int port = ss.getLocalPort();
142        ss.close();
143
144        String address = String.valueOf(port);
145
146        // launch the server debuggee
147        Process process = launch(address, "Exit0");
148
149        // wait for the debugge to be ready
150        while (!ready) {
151            try {
152                Thread.sleep(1000);
153            } catch(Exception ee) {
154                throw ee;
155            }
156        }
157
158        // attach to server debuggee and resume it so it can exit
159        AttachingConnector conn = (AttachingConnector)findConnector("com.sun.jdi.SocketAttach");
160        Map conn_args = conn.defaultArguments();
161        Connector.IntegerArgument port_arg =
162            (Connector.IntegerArgument)conn_args.get("port");
163        port_arg.setValue(port);
164
165        System.out.println("Connection arguments: " + conn_args);
166
167        VirtualMachine vm = conn.attach(conn_args);
168
169        // The first event is always a VMStartEvent, and it is always in
170        // an EventSet by itself.  Wait for it.
171        EventSet evtSet = vm.eventQueue().remove();
172        for (Event event: evtSet) {
173            if (event instanceof VMStartEvent) {
174                break;
175            }
176            throw new RuntimeException("Test failed - debuggee did not start properly");
177        }
178        vm.eventRequestManager().deleteAllBreakpoints();
179        vm.resume();
180
181        int exitCode = process.waitFor();
182
183        // if the server debuggee ran cleanly, we assume we were clean
184        if (exitCode == 0 && error_seen == 0) {
185            System.out.println("Test passed - server debuggee cleanly terminated");
186        } else {
187            throw new RuntimeException("Test failed - server debuggee generated an error when it terminated");
188        }
189    }
190}
191