# HG changeset patch # User lmesnik # Date 1544073507 28800 # Node ID 24ca55b8deed021fcaf418d8b26dc56bde1c1ec4 # Parent 4fd8872aebb4177a00567be22f7ce20105184754 8210107: vmTestbase/nsk/stress/network tests fail with Cannot assign requested address (Bind failed) Reviewed-by: dholmes, mseledtsov, chegar diff -r 4fd8872aebb4 -r 24ca55b8deed test/hotspot/jtreg/vmTestbase/nsk/stress/network/TEST.properties --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/network/TEST.properties Wed Dec 05 20:59:55 2018 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -# -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -exclusiveAccess.dirs=. diff -r 4fd8872aebb4 -r 24ca55b8deed test/hotspot/jtreg/vmTestbase/nsk/stress/network/network001.java --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/network/network001.java Wed Dec 05 20:59:55 2018 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,544 +0,0 @@ -/* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @key stress - * - * @summary converted from VM testbase nsk/stress/network/network001. - * VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick] - * VM testbase readme: - * DESCRIPTION - * This test transfers huge amount of data between server and client - * TCP/IP sockets, and checks if those data are transfered correctly. - * Both sockets are attached to local host name, or to the loopback - * "localhost" (having IP address 127.0.0.1). - * Information transfer is synchronized in this test. Client passes - * a large data parcel to server, and server reads that parcel and checks - * if it is same as expected (byte-to-byte equality). Then server passes - * (some other) parcel to client, and client reads and verifies those bytes. - * This ping-pong game is repeated 2000 times; and after that both sockets - * check if there are no extra bytes accudentally passed through their - * connection. - * Parcels lengths and contents are chosen randomly, and average parcel - * length is 125 bytes. So totally, each of the 2 sockets passes ~250Kb of - * data to its partner, and thus ~500Kb of data are transfered by this test. - * COMMENTS - * Note, that HotSpot 1.3beta-H fails to start this test due to the bug: - * #4245704 (P1/S1) Fails to launch with: jre/bin/net.dll ... - * - * @run main/othervm nsk.stress.network.network001 - */ - -package nsk.stress.network; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.Random; - -/** - * This test transfers huge amount of data between server and client - * TCP/IP sockets, and checks if those data are transfered correctly. - * Both sockets are attached to local host name, or to the loopback - * ``localhost'' (having IP address 127.0.0.1). - *

- *

Information transfer is synchronized in this test. Client passes - * a large data parcel to server, and server reads that parcel and checks - * if it is same as expected (byte-to-byte equality). Then server passes - * (some other) parcel to client, and client reads and verifies those bytes. - * This ping-pong game is repeated 2000 times; and after that both sockets - * check if there are no extra bytes accudentally passed through their - * connection. - *

- *

Parcels lengths and contents are chosen randomly, and average parcel - * length is 125 bytes. So totally, each of the 2 sockets passes ~250Kb of - * data to its partner, and thus ~500Kb of data are transfered by this test. - */ -public class network001 { - /** - * Number of parcels to be sent/recieve. - */ - private static final int DATA_PARCELS = 2000; - - /** - * Maximal length of data parcel to be sent/recieved - * (now it equals to 250 bytes). - */ - private static final int MAX_PARCEL = 250; - - /** - * Either actually display optional reports or not. - */ - static private final boolean DEBUG_MODE = false; - - /** - * Errors and optional reports log. Usually System.out. - */ - static private PrintStream out = System.out; - - /** - * Print error message: both client and server may print - * concurently. - */ - static private synchronized void println(Object message) { - out.println(message.toString()); - } - - /** - * Display optional report: comment ca va. - */ - static private void display(Object report) { - if (DEBUG_MODE) - println(report.toString()); - } - - /** - * Server thread intended to reply to data parcels sent by Client thread. - */ - static private class Server extends Thread { - /** - * This server thread listens the single socket. - */ - private ServerSocket serverSocket; - - /** - * Address and port of this server socket. - */ - public String toString() { - return serverSocket.toString(); - } - - /** - * Did the thread failed? If yes, what is the failure's reason. - */ - Exception exception = null; - - /** - * Which port does this socket is listening. - */ - int getPort() { - return serverSocket.getLocalPort(); - } - - /** - * Find some free port at the given address - * and attach new server to hear that port. - */ - Server(InetAddress address) throws IOException { - int someFreePort = 0; - int backlog = 50; // default for new ServerSocket(port) - serverSocket = new ServerSocket(someFreePort, backlog, address); - } - - /** - * Accept connection, read the string "abra", and respond "cadabra". - */ - public void run() { - try { - Socket socket = serverSocket.accept(); - display("Server socket: " + socket); - - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(0); - - for (int i = 0; i < DATA_PARCELS; i++) { - Parcel etalon = new Parcel(random); - - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - println("Server thread got unexpected parcel:"); - println("sample=" + sample); - println("etalon=" + etalon); - throw new TestFailure( - "server has read unexpected parcel"); - } - - etalon.send(ostream); - ostream.flush(); - } - - int datum = istream.read(); // wait for client close() - if (datum >= 0) - throw new TestFailure( - "server has read ambigous byte: " + datum); - - ostream.close(); // implies: socket.close(); - - } catch (Exception oops) { - exception = oops; - } - } - - } - - /** - * Client thread intended to send data parcels to Server thread and - * to recieve the server's replies. - */ - static private class Client extends Thread { - /** - * This thread uses the single client socket. - */ - private Socket socket; - - /** - * Address and port of this socket. - */ - public String toString() { - return socket.toString(); - } - - /** - * Did the thread failed? If yes, what is the failure's reason. - */ - Exception exception = null; - - /** - * Connect client socket on the given address - * and port. - */ - Client(InetAddress address, int port) throws IOException { - socket = new Socket(address, port); - } - - /** - * Accept connection, read the string "abra", and respond "cadabra". - */ - public void run() { - try { - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(0); - - for (int i = 0; i < DATA_PARCELS; i++) { - Parcel etalon = new Parcel(random); - etalon.send(ostream); - ostream.flush(); - - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - println("Client thread got unexpected parcel:"); - println("sample=" + sample); - println("etalon=" + etalon); - throw new TestFailure( - "parcel context is unexpected to client"); - } - } - - if (istream.available() > 0) { - int datum = istream.read(); - throw new TestFailure( - "client has read ambigous byte: " + datum); - } - ostream.close(); // implies: socket.close() - - } catch (Exception oops) { - exception = oops; - } - } - - } - - /** - * A data parcel to sent/recieved between Client and Server threads. - * When data parcel is sent, first 4 bytes transfered encode the size - * of the parcel (i.e.: number of data bytes in the parcel's contents). - * Then the parcel's contents bytes are transered. - */ - static class Parcel { - private byte[] parcel; - - /** - * Display all bytes as integer values from 0 to 255; - * or return ``null'' if this Parcel is not - * yet initialized. - */ - public String toString() { - if (parcel == null) - return "null"; - String s = "{"; - for (int i = 0; i < parcel.length; i++) - s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF); - return s + "}"; - } - - /** - * Generate new parcel[] array using the given - * random numbers generator. Client and Server - * threads should use identical random generators, - * so that those threads could generate equal data parcels and - * check the parcel just transfered. - */ - public Parcel(Random random) { - int size = random.nextInt(MAX_PARCEL) + 1; - parcel = new byte[size]; - for (int i = 0; i < size; i++) - parcel[i] = (byte) random.nextInt(256); - } - - /** - * Read exactly size bytes from the istream - * if possible, or throw TestFailure if unexpected end of - * istream occurs. - */ - private static byte[] readBytes(int size, InputStream istream) - throws IOException { - - byte data[] = new byte[size]; - for (int i = 0; i < size; i++) { - int datum = istream.read(); - if (datum < 0) - throw new TestFailure( - "unexpected EOF: have read: " + i + " bytes of " + size); - data[i] = (byte) datum; - } - return data; - } - - /** - * Read 4 bytes from istream and threat them to encode - * size of data parcel following these 4 bytes. - */ - private static int getSize(InputStream istream) throws IOException { - byte data[] = readBytes(4, istream); - int data0 = (int) data[0] & 0xFF; - int data1 = (int) data[1] & 0xFF; - int data2 = (int) data[2] & 0xFF; - int data3 = (int) data[3] & 0xFF; - int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24); - int size = sizeWord + 1; - if (size <= 0) - throw new TestFailure("illegal size: " + size); - return size; - } - - /** - * Send 4 bytes encoding actual size of the parcel just to be transfered. - */ - private static void putSize(OutputStream ostream, int size) - throws IOException { - - if (size <= 0) - throw new TestFailure("illegal size: " + size); - - int sizeWord = size - 1; - byte data[] = new byte[4]; - data[0] = (byte) sizeWord; - data[1] = (byte) (sizeWord >> 8); - data[2] = (byte) (sizeWord >> 16); - data[3] = (byte) (sizeWord >> 24); - ostream.write(data); - } - - /** - * Recieve data parcel. - */ - public Parcel(InputStream istream) throws IOException { - int size = getSize(istream); - parcel = readBytes(size, istream); - } - - /** - * Send this data parcel. - */ - public void send(OutputStream ostream) throws IOException { - int size = parcel.length; - putSize(ostream, size); - ostream.write(parcel); - } - - /** - * Check byte-to-byte equality between this and the - * other parcels. - */ - public boolean equals(Parcel other) { - if (this.parcel.length != other.parcel.length) - return false; - int size = parcel.length; - for (int i = 0; i < size; i++) - if (this.parcel[i] != other.parcel[i]) - return false; - return true; - } - - } - - /** - * Server or Client thread may throw this exception to report the test - * failure. - */ - static class TestFailure extends RuntimeException { - /** - * Report particular purpose of the test failure. - */ - public TestFailure(String purpose) { - super(purpose); - } - - } - - /** - * Attach client and server sockets to the local host, and check if - * huge amount of data could be correctly transfered between these - * sockets. - *

- *

Command-line parameters provided with args[] may - * prompt the local host IP address or domain name. Execute: - *
   - * java network001 [IP-address | host_name | - * localhost ] - *
where parameters are: - *
   - * IP-address - local hots's address, or 127.0.0.1 - *
   - * host_name - local host's domain name, or the - * keyword ``localhost'' - *
   - * localhost - placeholder for the IP-address 127.0.0.1 - *
By default, the test uses the Internet address available via - * the method InetAddress.getLocalHost() - */ - public static int run(String args[], PrintStream out) { - network001.out = out; - - // - // Get IP address of the local machine. - // - - InetAddress address = null; - try { - switch (args.length) { - case 0: - address = InetAddress.getLocalHost(); - break; - case 1: - String hostName = args[0]; - address = InetAddress.getByName(args[0]); - break; - default: - println("Use:"); - println(" java network001"); - println("or:"); - println(" java network001 ${IP_ADDRESS}"); - println("or:"); - println(" java network001 ${HOST_NAME}"); - println("or:"); - println(" java network001 localhost"); - return 2; // FAILED - } - } catch (UnknownHostException exception) { - println(exception); - return 2; // FAILED - } - display("Host: " + address); - - // - // Incarnate the server & the client sockets. - // - - Server server = null; - try { - server = new Server(address); - } catch (IOException io) { - println("Failed to create server: " + io); - return 2; - } - display("Server: " + server); - - int port = server.getPort(); - - Client client = null; - try { - client = new Client(address, port); - } catch (IOException io) { - out.println("Failed to create client: " + io); - return 2; - } - display("Client socket: " + client); - - // - // Execute the server and client threads. - // - - Exception exception = null; - try { - server.start(); - client.start(); - while (client.isAlive() || server.isAlive()) - if (client.exception == null && server.exception == null) - Thread.yield(); - else - break; - } catch (TestFailure failure) { - exception = failure; - } - - // Failure diagnostics, if needed. - - Exception problem[] = new Exception[3]; - problem[0] = exception; - problem[1] = server.exception; - problem[2] = client.exception; - - int exitCode = 0; - - for (int i = 0; i < 3; i++) - if (problem[i] != null) { - out.println("#### OOPS ! ####"); - problem[i].printStackTrace(out); - exitCode = 2; - } - - if (exitCode != 0) { - out.println("#### OOPS ! ####"); - out.println("# Test failed."); - return 2; // FAILED - } - display("Test passed."); - return 0; // PASSED - } - - /** - * Re-calls to the method run(args[],out) actually - * performing the test; and stop with exit code 95 if the test - * has passed, or with code 97 if the test has failed. - * (This is JCK-like exit codes convention.) - * - * @see #run(String[], PrintStream) - */ - public static void main(String args[]) { - int exitCode = run(args, System.out); - System.exit(exitCode + 95); - // JCK-like exit code. - } - -} diff -r 4fd8872aebb4 -r 24ca55b8deed test/hotspot/jtreg/vmTestbase/nsk/stress/network/network002.java --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/network/network002.java Wed Dec 05 20:59:55 2018 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,697 +0,0 @@ -/* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - - -/* - * @test - * @key stress - * - * @summary converted from VM testbase nsk/stress/network/network002. - * VM testbase keywords: [stress, slow, nonconcurrent, quick] - * VM testbase readme: - * DESCRIPTION - * This test transfers huge amount of data between 2 Java virtual machines - * using the TCP/IP protocol, and checks if those data are transfered correctly. - * Both client and server VMs run on the same local computer and attach TCP/IP - * sockets to the local host, or to the loopback domain "localhost" (having IP - * address 127.0.0.1). - * Information transfer is synchronized in this test. Client VM passes - * a large data parcel to server VM, and server reads that parcel and checks - * if it is same as expected (byte-to-byte equality). Then server passes - * (some other) parcel to client, and client reads and verifies those data. - * This ping-pong game is repeated 2000 times; and after that both VMs check - * if there are no extra bytes accudentally passed through their connection. - * Parcels lengths and contents are chosen randomly, and average parcel - * length is 125 bytes. So totally, each of the 2 VMs passes ~250Kb of data - * to its partner, and thus ~500Kb of data are transfered by this test. - * COMMENTS - * HotSpot 1.3beta-H fails to start this test due to the hotspot bug: - * #4245704 (P1/S1) Fails to launch with: jre/bin/net.dll ... - * Test was fixed: - * added WAITTIME parameter defined timeout for TCP/IP sockets in minutes - * - * @library /vmTestbase - * /test/lib - * @run driver jdk.test.lib.FileInstaller . . - * @build nsk.stress.network.network002 - * @run main/othervm PropertyResolvingWrapper - * nsk.stress.network.network002 - * "${test.jdk}/bin/java ${test.vm.opts} ${test.java.opts}" 5 - */ - -package nsk.stress.network; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.Random; - -/** - * This test transfers huge amount of data between 2 Java virtual machines - * using the TCP/IP protocol, and checks if those data are transfered correctly. - * Both client and server VMs run on the same local computer and attach TCP/IP - * sockets to the local host, or to the loopback domain ``localhost'' - * (having IP address 127.0.0.1). - *

- *

Information transfer is synchronized in this test. Client VM passes - * a large data parcel to server VM, and server reads that parcel and checks - * if it is same as expected (byte-to-byte equality). Then server passes - * (some other) parcel to client, and client reads and verifies those data. - * This ping-pong game is repeated 2000 times; and after that both VMs check - * if there are no extra bytes accudentally passed through their connection. - *

- *

Parcels lengths and contents are chosen randomly, and average parcel - * length is 125 bytes. So totally, each of the 2 VMs passes ~250Kb of data - * to its partner, and thus ~500Kb of data are transfered by this test. - */ -public class network002 { - /** - * Timeout for TCP/IP sockets (currently set to 1 min). - */ - private static int SO_TIMEOUT; - - /** - * Number of parcels to be sent/recieved. - */ - private static final int DATA_PARCELS = 2000; - - /** - * Maximal length of data parcel to be sent/recieved. - */ - private static final int MAX_PARCEL = 250; - - /** - * Either actually display optional reports or not. - */ - static private final boolean DEBUG_MODE = false; - - //----------------------------------------------------------------// - - /** - * Re-calls to the method run(args[],out) actually - * performing the test. After run(args[],out) stops, - * follow JDK-like convention for exit codes. I.e.: stop with - * exit status 95 if the test has passed, or with status 97 if - * the test has failed. - * - * @see #run(String[], PrintStream) - */ - public static void main(String args[]) { - int exitCode = run(args, System.out); - System.exit(exitCode + 95); - // JCK-like exit status. - } - - /** - * Incarnate new network002 instance reporting to the given - * out stream, and invoke the method run(args) - * for that instance to perform the test. - */ - public static int run(String args[], PrintStream out) { - network002 test = new network002(out); - int exitCode = test.run(args); - return exitCode; - } - - /** - * Parse command-line parameters stored into args[] array, - * then perform the test. I.e.: start the server thread at the same VM - * this method runs, then start the other client VM, and verify data - * transfer through TCP/IP connection between those different virtual - * machines. - *

- *

There should be 1 or 2 command-line parameters: - *
   - * java network002 java_command waittime - * [IP-address | host_name | localhost ] - *
where parameters are: - *
   - * java_command - how to start java, - * e.g.: ``c:\jdk1.3\bin\java -classic'' - *
   - * waittime - timeout for TCP/IP sockets in minutes - *
   - * IP-address - local hots's address, or 127.0.0.1 - *
   - * host_name - local host's domain name, or the - * keyword ``localhost'' - *
   - * localhost - placeholder for the IP-address 127.0.0.1 - *

- *

Usually, java_command should point to the same - * Java machine just executing this test. However, every compatible Java 2 - * implementation is appropriate. - *

- *

If optional parameter is ommited, the test invokes the method - * InetAddress.getLocalHost() to get the domain name and - * IP-address of the local computer. - */ - private int run(String args[]) { - // - // Get the Internet address of the local machine. - // - InetAddress address = null; - try { - switch (args.length) { - case 2: - address = InetAddress.getLocalHost(); - break; - case 3: - address = InetAddress.getByName(args[2]); - break; - default: - complain("Illegal arguments number; execute:"); - complain(" java network002 $JAVA_COMMAND " + - "[$IP_ADDRESS | $HOST_NAME | localhost]"); - return 2; // FAILED - } - } catch (UnknownHostException exception) { - complain(exception.toString()); - return 2; // FAILED - } - display("Host: " + address); - - // - // Start the server thread on the same VM this method just runs. - // - Server server = null; - try { - server = new Server(address); - server.start(); - } catch (Exception exception) { - complain("Failed to start server: " + exception); - return 2; - } - display("Server: " + server); - - // - // Start the client process on different VM. - // - String IPAddress = server.getIPAddress(); // e.g.: 127.0.0.1 - int port = server.getPort(); - String command = args[0] + " " + network002.class.getName() + "$Client " + IPAddress + " " + port; - try { - SO_TIMEOUT = Integer.parseInt(args[1]) * 60 * 1000; - } catch (NumberFormatException e) { - complain("Wrong timeout argument: " + e); - return 2; - } - - Runtime runtime = Runtime.getRuntime(); - - Process client = null; - IORedirector redirectOut = null; - IORedirector redirectErr = null; - - try { - client = runtime.exec(command); - - InputStream clientOut = client.getInputStream(); - InputStream clientErr = client.getErrorStream(); - redirectOut = new IORedirector(clientOut, DEBUG_MODE ? out : null); - redirectErr = new IORedirector(clientErr, out); - redirectOut.start(); - redirectErr.start(); - - } catch (Exception exception) { - complain("Failed to start client: " + exception); - return 2; - } - - // - // Wait until the server and client both stop. - // - try { - client.waitFor(); - if (redirectOut.isAlive()) - redirectOut.join(); - if (redirectErr.isAlive()) - redirectErr.join(); - - // If client has crashed, also terminate the server (to avoid hangup). - int clientStatus = client.exitValue(); - if (clientStatus != 95) { - complain(""); - complain("Client VM has crashed: exit status=" + clientStatus); - if (server.isAlive()) - complain("Server also should be terminated."); - complain("Test failed."); - return 2; // failure - } - - // Client has finished OK; wait for the server. - if (server.isAlive()) - server.join(); - - } catch (Exception exception) { - complain("Test interrupted: " + exception); - complain("Test failed."); - return 2; // FAILURE - } - - // - // Complain failure, if occured. - // - - if (server.exception != null) { - complain("Server exception: " + server.exception); - complain("Test failed."); - return 2; // failure - } - - display("Test passed."); - return 0; // Ok - } - - //----------------------------------------------------------------// - - /** - * The test should report to the given out stream. - */ - private network002(PrintStream out) { - this.out = out; - } - - /** - * Log stream for error messages and/or (optional) execution trace. - */ - private PrintStream out; - - /** - * Print error message. - */ - private void complain(Object message) { - out.println("# " + message); - out.flush(); - } - - /** - * Display optional report: comment ca va? - */ - private void display(Object report) { - if (DEBUG_MODE) - out.println(report.toString()); - out.flush(); - } - - //----------------------------------------------------------------// - - /** - * Server thread should reply to data parcels sent by Client VM. - */ - private class Server extends Thread { - /** - * The socket to listen for a client. - */ - private ServerSocket serverSocket; - - /** - * Display the server socket. - */ - public String toString() { - return serverSocket.toString(); - } - - /** - * Server's IP-address in the form ``x.y.u.z'', - * or ``127.0.0.1'' for loopback connection. - */ - public String getIPAddress() { - return serverSocket.getInetAddress().getHostAddress(); - } - - /** - * Which port is this socket listening? - */ - int getPort() { - return serverSocket.getLocalPort(); - } - - /** - * Find some free port at the given address - * and attach new server to hear that port. - */ - public Server(InetAddress address) throws IOException { - int someFreePort = 0; - int backlog = 50; // default for new ServerSocket(port) - serverSocket = new ServerSocket(someFreePort, backlog, address); - } - - /** - * Exception just arisen while the server was working, - * or null if it was OK with the server. - */ - Exception exception = null; - - /** - * Accept connection, then reply to client's parcels. - */ - public void run() { - try { - Socket socket = serverSocket.accept(); - socket.setSoTimeout(SO_TIMEOUT); - - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(0); - - for (int i = 0; i < DATA_PARCELS; i++) { - display("Server: i=" + i); - Parcel etalon = new Parcel(random); - - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - complain("Server got unexpected parcel:\n" - + "sample=" + sample + "\n" - + "etalon=" + etalon); - throw new TestFailure( - "the parcel just read seems wrong for server"); - } - - etalon.send(ostream); - ostream.flush(); - } - - int datum = istream.read(); // wait for client close() - if (datum >= 0) - throw new TestFailure( - "server has read ambigous byte: " + datum); - - ostream.close(); // implies: socket.close(); - - } catch (Exception oops) { - exception = oops; - } - } - - } - - //----------------------------------------------------------------// - - /** - * Client VM should send data parcels to Server VM and - * recieve and verify the server's replies. - */ - private static class Client { - /** - * Print error message. - */ - private static void complain(Object message) { - System.err.println("# " + message); - System.err.flush(); - } - - /** - * Display execution trace. - */ - private static void display(Object message) { - System.out.println(message.toString()); - System.out.flush(); - } - - /** - * Exit with JCK-like status. - */ - private static void exit(int exitCode) { - System.exit(exitCode + 95); - } - - /** - * Atack server with huge data parcels, and check if it replies correctly. - * The command-line parameters prescribe the server's IP-address and port: - *
   - * java network002$Client IP-address port - *
where: - *
   - * IP-address - local host's address, - * or 127.0.0.1 - *
   - * port - some port assigned by server - */ - public static void main(String args[]) { - if (args.length != 2) { - complain("Illegal number of client paramenets, try:"); - complain(" java network002$Client IP-address port"); - exit(2); // FAILED - } - - try { - InetAddress address = InetAddress.getByName(args[0]); - int port = Integer.parseInt(args[1]); - - Socket socket = new Socket(address, port); - socket.setSoTimeout(SO_TIMEOUT); - display("Client: " + socket); - - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(0); - - for (int i = 0; i < DATA_PARCELS; i++) { - display("Client: i=" + i); - Parcel etalon = new Parcel(random); - etalon.send(ostream); - ostream.flush(); - - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - complain("Client got unexpected parcel:\n" - + "sample=" + sample + "\n" - + "etalon=" + etalon); - throw new TestFailure( - "parcel context is unexpected to client"); - } - } - - if (istream.available() > 0) { - int datum = istream.read(); - throw new TestFailure( - "client has read ambigous byte: " + datum); - } - ostream.close(); // implies: socket.close() - - } catch (Exception exception) { - complain("Client exception: " + exception); - exit(2); // FAILED - } - exit(0); // PASSED, at least at the client side. - } - - } - - /** - * Two of such threads should redirect out and err - * streams of client VM. - */ - private static class IORedirector extends Thread { - /** - * Source stream. - */ - InputStream in; - /** - * Destination stream. - */ - OutputStream out; - - /** - * Redirect in to out. - */ - public IORedirector(InputStream in, OutputStream out) { - this.in = in; - this.out = out; - } - - /** - * Read input stream until the EOF, and write everithing to output stream. - * If output stream is assigned to null, do not print anything, - * but read the input stream anywhere. - */ - public void run() { - try { - for (; ; ) { - int symbol = in.read(); - if (symbol < 0) - break; // EOF - if (out != null) - out.write(symbol); - } - - if (out != null) - out.flush(); - - } catch (Exception exception) { - throw new TestFailure("IORedirector exception: " + exception); - } - } - } - - //----------------------------------------------------------------// - - /** - * A data parcel to be sent/recieved between Client VM and Server thread. - * When data parcel is sent, first 4 bytes are transfered which encode the - * int number equal to size of the parcel minus 1. I.e.: if - * number of data bytes in the parcel's contents is N, then - * the first 4 bytes encode the number N-1. After that, the - * parcel's contents bytes are transered. - */ - static class Parcel { - private byte[] parcel; - - /** - * Display all bytes as integer values from 0 to 255; - * or return ``null'' if this Parcel is not - * yet initialized. - */ - public String toString() { - if (parcel == null) - return "null"; - String s = "{"; - for (int i = 0; i < parcel.length; i++) - s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF); - return s + "}"; - } - - /** - * Generate new parcel[] array using the given - * random numbers generator. Client and Server - * threads should use identical random generators, - * so that those threads could generate equal data parcels and - * check the parcel just transfered. - */ - public Parcel(Random random) { - int size = random.nextInt(MAX_PARCEL) + 1; - parcel = new byte[size]; - for (int i = 0; i < size; i++) - parcel[i] = (byte) random.nextInt(256); - } - - /** - * Read exactly size bytes from the istream - * if possible, or throw TestFailure if unexpected end of - * istream occurs. - */ - private static byte[] readBytes(int size, InputStream istream) - throws IOException { - - byte data[] = new byte[size]; - for (int i = 0; i < size; i++) { - int datum = istream.read(); - if (datum < 0) - throw new TestFailure( - "unexpected EOF: have read: " + i + " bytes of " + size); - data[i] = (byte) datum; - } - return data; - } - - /** - * Read 4 bytes from istream and threat them to encode - * size of data parcel following these 4 bytes. - */ - private static int getSize(InputStream istream) throws IOException { - byte data[] = readBytes(4, istream); - int data0 = (int) data[0] & 0xFF; - int data1 = (int) data[1] & 0xFF; - int data2 = (int) data[2] & 0xFF; - int data3 = (int) data[3] & 0xFF; - int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24); - int size = sizeWord + 1; - if (size <= 0) - throw new TestFailure("illegal size: " + size); - return size; - } - - /** - * Send 4 bytes encoding actual size of the parcel just to be transfered. - */ - private static void putSize(OutputStream ostream, int size) - throws IOException { - - if (size <= 0) - throw new TestFailure("illegal size: " + size); - - int sizeWord = size - 1; - byte data[] = new byte[4]; - data[0] = (byte) sizeWord; - data[1] = (byte) (sizeWord >> 8); - data[2] = (byte) (sizeWord >> 16); - data[3] = (byte) (sizeWord >> 24); - ostream.write(data); - } - - /** - * Recieve data parcel. - */ - public Parcel(InputStream istream) throws IOException { - int size = getSize(istream); - parcel = readBytes(size, istream); - } - - /** - * Send this data parcel. - */ - public void send(OutputStream ostream) throws IOException { - int size = parcel.length; - putSize(ostream, size); - ostream.write(parcel); - } - - /** - * Check byte-to-byte equality between this and the - * other parcels. - */ - public boolean equals(Parcel other) { - if (this.parcel.length != other.parcel.length) - return false; - int size = parcel.length; - for (int i = 0; i < size; i++) - if (this.parcel[i] != other.parcel[i]) - return false; - return true; - } - - } - - /** - * Server or Client may throw this exception to report the test failure. - */ - static class TestFailure extends RuntimeException { - /** - * Report particular purpose of the test failure. - */ - public TestFailure(String purpose) { - super(purpose); - } - - } - -} diff -r 4fd8872aebb4 -r 24ca55b8deed test/hotspot/jtreg/vmTestbase/nsk/stress/network/network003.java --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/network/network003.java Wed Dec 05 20:59:55 2018 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,658 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* - * @test - * @key stress - * - * @summary converted from VM testbase nsk/stress/network/network003. - * VM testbase keywords: [stress, slow, nonconcurrent, quick] - * VM testbase readme: - * DESCRIPTION - * This test transfers huge amount of data between one server and multiple - * clients communicating via TCP/IP sockets, and checks if those data are - * transfered correctly. All TCP/IP sockets are attached to local host - * (by its domain name), or to the ``localhost'' loopback (having the IP - * address 127.0.0.1). - * In this test, 128 client/server connections are established. Once a - * connection is established, client passes a large data parcel to server, - * and server reads that parcel and checks if it is same as expected - * (byte-to-byte equality is desired). Then server passes (some other) parcel - * to the client, and client reads and verifies those bytes. This ping-pong - * game is repeated 128 times; and after that each pair of sockets checks if - * there are no extra bytes accudentally passed through their connection. - * Parcels lengths and contents are chosen randomly, and average parcel - * length is 128 bytes. So totally, each pair of sockets passes ~16Kb of - * data to each other, and thus ~32Kb of data are transfered by each sockets - * pair. Totally, ~4Mb of data are transfered by all client/server pairs. - * COMMENTS - * The production Solaris_JDK_1.3-b12 Server VM crashes under this test: - * # - * # HotSpot Virtual Machine Error, Unexpected Signal 10 - * # Please report this error at - * # http://java.sun.com/cgi-bin/bugreport.cgi - * # - * # Error ID: 4F533F534F4C415249530E43505007D9 01 - * # - * # Problematic Thread: prio=5 tid=0x214418 nid=0x103 runnable - * # - * (ErrorID == "os_solaris.cpp, 2009") - * - * @run main/othervm nsk.stress.network.network003 - */ - -package nsk.stress.network; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.Random; - -/** - * This test transfers huge amount of data between one server and multiple - * clients communicating via TCP/IP sockets, and checks if those data are - * transfered correctly. All TCP/IP sockets are attached to local host - * (by its domain name), or to the ``localhost'' loopback (having the IP - * address 127.0.0.1). - *

- *

In this test, 128 client/server connections are established. Once a - * connection is established, client passes a large data parcel to server, - * and server reads that parcel and checks if it is same as expected - * (byte-to-byte equality is desired). Then server passes (some other) parcel - * to the client, and client reads and verifies those bytes. This ping-pong - * game is repeated 128 times; and after that each pair of sockets checks if - * there are no extra bytes accudentally passed through their connection. - *

- *

Parcels lengths and contents are chosen randomly, and average parcel - * length is 128 bytes. So totally, each pair of sockets passes ~16Kb of - * data to each other, and thus ~32Kb of data are transfered by each sockets - * pair. Totally, ~4Mb of data are transfered by all client/server pairs. - */ -public class network003 { - /** - * Do actually display optional reports? - */ - static private final boolean DEBUG_MODE = false; - - /** - * Errors and optional reports log. Usually System.out. - */ - static private PrintStream out = System.out; - - /** - * Print error message: all clients and servers may print concurently. - */ - static private synchronized void println(Object message) { - out.println(message.toString()); - } - - /** - * Display optional report: comment ca va. - */ - static private void display(Object report) { - if (DEBUG_MODE) - println(report.toString()); - } - - /** - * Maximal number of connections this test should open simultaneously. - */ - private final static int MAX_CONNECTIONS = 128; - - /** - * Check few more connections to make sure that MAX_CONNECTIONS are safe. - */ - private final static int CONNECTIONS_RESERVE = 10; - - /** - * Number of client/server connections to establish. - */ - private static final int CONNECTIONS = detectOSLimitation(); - - /** - * Number of parcels to be sent/recieved. - */ - private static final int DATA_PARCELS = 128; - - /** - * Maximal length of data parcel to be sent/recieved - * (it equals to 256 bytes now). - */ - private static final int MAX_PARCEL = 1 << 8; - - /** - * How many IP sockets can we open simultaneously? - * Check if MAX_CONNECTIONS connections - * can be open simultaneously. - */ - private static int detectOSLimitation() { - final int CONNECTIONS_TO_TRY = MAX_CONNECTIONS + CONNECTIONS_RESERVE; - ServerSocket ssoc[] = new ServerSocket[CONNECTIONS_TO_TRY]; - display("--- Trying to open " + CONNECTIONS_TO_TRY + " connections:"); - int i; - for (i = 0; i < CONNECTIONS_TO_TRY; i++) - try { - ssoc[i] = new ServerSocket(0); - display("--- Open: ssoc[" + i + "] = " + ssoc[i]); - } catch (IOException ioe) { - display("--- OOPS! -- failed to open connection #" + i); - break; - } - display("--- Could open " + - (i < CONNECTIONS_TO_TRY ? "only " : "") + i + " connections."); - display("--- Closing them:"); - for (int j = 0; j < i; j++) - try { - ssoc[j].close(); - } catch (IOException ioe) { - throw new Error("FATAL error while loading the test: " + ioe); - } - display("--- OK."); - int safeConnections = i - CONNECTIONS_RESERVE; - if (safeConnections < 1) - safeConnections = 1; - if (safeConnections < MAX_CONNECTIONS) { - println("# ------------------------- CAUTION: -------------------"); - println("# While checking the OS limitations, the test found that"); - println("# only " + i + " TCP/IP socket connections could be safely open"); - println("# simultaneously. However, possibility to open at least"); - println("# " + MAX_CONNECTIONS + "+" + CONNECTIONS_RESERVE - + " connections were expected."); - println("# "); - println("# So, the test will check only " + safeConnections + " connection" - + (safeConnections == 1 ? "" : "s") + " which seem"); - println("# safe to be open simultaneously."); - println("# ------------------------------------------------------"); - } - return safeConnections; - } - - /** - * Server thread intended to reply to data parcels sent by Client thread. - */ - static private class Server extends Thread { - /** - * This server thread listens the single socket. - */ - private ServerSocket serverSocket; - - /** - * Address and port of this server socket. - */ - public String toString() { - return serverSocket.toString(); - } - - /** - * Did the thread failed? If yes, what is the failure's reason. - */ - Exception exception = null; - - /** - * What is the port number this socket is listening for? - */ - int getPort() { - return serverSocket.getLocalPort(); - } - - /** - * Find some free port at the given address - * and attach new server to hear that port. - */ - Server(InetAddress address) throws IOException { - int someFreePort = 0; - int backlog = 50; // default for new ServerSocket(port) - serverSocket = new ServerSocket(someFreePort, backlog, address); - } - - /** - * Accept connection, then read/respond DATA_PARCELS parcels - * of random data. Set initial seed for pseudo-random numbers generator - * to the value of the local port number. - * - * @see #DATA_PARCELS - * @see #getPort() - */ - public void run() { - try { - Socket socket = serverSocket.accept(); - display("Server socket: " + socket); - - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(getPort()); - - for (int i = 0; i < DATA_PARCELS; i++) { - Parcel etalon = new Parcel(random); - - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - println("Server thread for port #" - + getPort() + " got unexpected parcel:\n" - + "sample=" + sample + "\n" - + "etalon=" + etalon); - throw new TestFailure( - "server has read unexpected parcel"); - } - - etalon.send(ostream); - ostream.flush(); - } - - int datum = istream.read(); // wait for client close() - if (datum >= 0) - throw new TestFailure( - "server has read ambigous byte: " + datum); - - ostream.close(); // implies: socket.close(); - - } catch (Exception oops) { - exception = oops; - } - } - - } - - /** - * Client thread intended to send data parcels to Server thread and - * to recieve the server's replies. - */ - static private class Client extends Thread { - /** - * This thread uses the single client socket. - */ - private Socket socket; - - /** - * Address and port of this socket. - */ - public String toString() { - return socket.toString(); - } - - /** - * Did the thread failed? If yes, what is the failure's reason. - */ - Exception exception = null; - - /** - * Connect client socket on the given address - * and port. - */ - Client(InetAddress address, int port) throws IOException { - socket = new Socket(address, port); - } - - /** - * What is the port number this socket is listening for? - */ - int getPort() { - return socket.getPort(); - } - - - /** - * Establish connection, then read/respond DATA_PARCELS parcels - * of random data. Set initial seed for pseudo-random numbers generator - * to the value of the local port number. - * - * @see #DATA_PARCELS - * @see #getPort() - */ - public void run() { - try { - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(getPort()); - - for (int i = 0; i < DATA_PARCELS; i++) { - Parcel etalon = new Parcel(random); - etalon.send(ostream); - ostream.flush(); - - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - println("Client thread for port #" - + getPort() + " got unexpected parcel:\n" - + "sample=" + sample + "\n" - + "etalon=" + etalon); - throw new TestFailure( - "parcel context is unexpected to client"); - } - } - - if (istream.available() > 0) { - int datum = istream.read(); - throw new TestFailure( - "client has read ambigous byte: " + datum); - } - ostream.close(); // implies: socket.close() - - } catch (Exception oops) { - exception = oops; - } - } - - } - - /** - * A data parcel to sent/recieved between Client and Server threads. - * When data parcel is sent, first 4 bytes transfered encode the size - * of the parcel (i.e.: number of data bytes in the parcel's contents). - * Then the parcel's contents bytes are transered. - */ - static class Parcel { - private byte[] parcel; - - /** - * Display all bytes as integer values from 0 to 255; - * or return ``null'' if this Parcel is not - * yet initialized. - */ - public String toString() { - if (parcel == null) - return "null"; - String s = "{"; - for (int i = 0; i < parcel.length; i++) - s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF); - return s + "}"; - } - - /** - * Generate new parcel[] array using the given - * random numbers generator. Client and Server - * threads should use identical random generators, - * so that those threads could generate equal data parcels and - * check the parcel just transfered. - */ - public Parcel(Random random) { - int size = random.nextInt(MAX_PARCEL) + 1; - parcel = new byte[size]; - for (int i = 0; i < size; i++) - parcel[i] = (byte) random.nextInt(256); - } - - /** - * Read exactly size bytes from the istream - * if possible, or throw TestFailure if unexpected end of - * istream occurs. - */ - private static byte[] readBytes(int size, InputStream istream) - throws IOException { - - byte data[] = new byte[size]; - for (int i = 0; i < size; i++) { - int datum = istream.read(); - if (datum < 0) - throw new TestFailure( - "unexpected EOF: have read: " + i + " bytes of " + size); - data[i] = (byte) datum; - } - return data; - } - - /** - * Read 4 bytes from istream and threat them to encode - * size of data parcel following these 4 bytes. - */ - private static int getSize(InputStream istream) throws IOException { - byte data[] = readBytes(4, istream); - int data0 = (int) data[0] & 0xFF; - int data1 = (int) data[1] & 0xFF; - int data2 = (int) data[2] & 0xFF; - int data3 = (int) data[3] & 0xFF; - int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24); - int size = sizeWord + 1; - if (size <= 0) - throw new TestFailure("illegal size: " + size); - return size; - } - - /** - * Send 4 bytes encoding actual size of the parcel just to be transfered. - */ - private static void putSize(OutputStream ostream, int size) - throws IOException { - - if (size <= 0) - throw new TestFailure("illegal size: " + size); - - int sizeWord = size - 1; - byte data[] = new byte[4]; - data[0] = (byte) sizeWord; - data[1] = (byte) (sizeWord >> 8); - data[2] = (byte) (sizeWord >> 16); - data[3] = (byte) (sizeWord >> 24); - ostream.write(data); - } - - /** - * Recieve data parcel. - */ - public Parcel(InputStream istream) throws IOException { - int size = getSize(istream); - parcel = readBytes(size, istream); - } - - /** - * Send this data parcel. - */ - public void send(OutputStream ostream) throws IOException { - int size = parcel.length; - putSize(ostream, size); - ostream.write(parcel); - } - - /** - * Check byte-to-byte equality between this and the - * other parcels. - */ - public boolean equals(Parcel other) { - if (this.parcel.length != other.parcel.length) - return false; - int size = parcel.length; - for (int i = 0; i < size; i++) - if (this.parcel[i] != other.parcel[i]) - return false; - return true; - } - - } - - /** - * Server or Client thread may throw this exception to report the test - * failure. - */ - static class TestFailure extends RuntimeException { - /** - * Report particular purpose of the test failure. - */ - public TestFailure(String purpose) { - super(purpose); - } - - } - - /** - * Attach client and server sockets to the local host, and check if - * huge amount of data could be correctly transfered between these - * sockets. - *

- *

Command-line parameters provided with args[] may - * prompt the local host IP address or domain name. Execute: - *
   - * java network003 [IP-address | host_name | - * localhost ] - *
where parameters are: - *
   - * IP-address - local hots's address, or 127.0.0.1 - *
   - * host_name - local host's domain name, or the - * keyword ``localhost'' - *
   - * localhost - placeholder for the IP-address 127.0.0.1 - *
By default, the test uses the Internet address available via - * the method InetAddress.getLocalHost() - */ - public static int run(String args[], PrintStream out) { - network003.out = out; - - // - // Get IP address of the local machine. - // - - InetAddress address = null; - try { - switch (args.length) { - case 0: - address = InetAddress.getLocalHost(); - break; - case 1: - String hostName = args[0]; - address = InetAddress.getByName(args[0]); - break; - default: - println("Use:"); - println(" java network003"); - println("or:"); - println(" java network003 ${IP_ADDRESS}"); - println("or:"); - println(" java network003 ${HOST_NAME}"); - println("or:"); - println(" java network003 localhost"); - return 2; // FAILED - } - } catch (UnknownHostException exception) { - println(exception); - return 2; // FAILED - } - display("Host: " + address); - - // - // Incarnate the server & the client sockets. - // - - Server server[] = new Server[CONNECTIONS]; - Client client[] = new Client[CONNECTIONS]; - - for (int i = 0; i < CONNECTIONS; i++) { - try { - server[i] = new Server(address); - } catch (IOException io) { - println("Failed to create server #" + i + ": " + io); - return 2; - } - display("Server #" + i + ": " + server[i]); - } - - for (int i = 0; i < CONNECTIONS; i++) { - int port = server[i].getPort(); - try { - client[i] = new Client(address, port); - } catch (IOException io) { - out.println("Failed to create client #" + i + ": " + io); - return 2; - } - display("Client socket #" + i + ": " + client[i]); - } - - // - // Execute the server and client threads. - // - - Exception exception = null; - try { - for (int i = 0; i < CONNECTIONS; i++) - server[i].start(); - for (int i = 0; i < CONNECTIONS; i++) - client[i].start(); - boolean someIsAlive = true; - while (someIsAlive) { - boolean aliveFound = false; - boolean someBroken = false; - for (int i = 0; i < CONNECTIONS; i++) - if (client[i].isAlive() || server[i].isAlive()) { - if ((client[i].exception != null) || - (server[i].exception != null)) - someBroken = true; - aliveFound = true; - Thread.yield(); - } - someIsAlive = aliveFound; - if (someBroken) - break; - } - } catch (TestFailure failure) { - exception = failure; - } - - // Failure diagnostics, if needed. - - Exception problem[] = new Exception[2 * CONNECTIONS + 1]; - problem[0] = exception; - for (int i = 0; i < CONNECTIONS; i++) { - problem[2 * i + 1] = server[i].exception; - problem[2 * i + 2] = client[i].exception; - } - - int exitCode = 0; - - for (int i = 0; i < 2 * CONNECTIONS + 1; i++) - if (problem[i] != null) { - out.println("#### OOPS ! ####"); - problem[i].printStackTrace(out); - exitCode = 2; - } - - if (exitCode != 0) { - out.println("#### OOPS ! ####"); - out.println("# Test failed."); - return 2; // FAILED - } - display("Test passed."); - return 0; // PASSED - } - - /** - * Re-calls to the method run(args[],out) actually - * performing the test; and stop with exit code 95 if the test - * has passed, or with code 97 if the test has failed. - * (This is JCK-like exit codes convention.) - * - * @see #run(String[], PrintStream) - */ - public static void main(String args[]) { - int exitCode = run(args, System.out); - System.exit(exitCode + 95); - // JCK-like exit code. - } - -} diff -r 4fd8872aebb4 -r 24ca55b8deed test/hotspot/jtreg/vmTestbase/nsk/stress/network/network004.java --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/network/network004.java Wed Dec 05 20:59:55 2018 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,878 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* - * @test - * @key stress - * - * @summary converted from VM testbase nsk/stress/network/network004. - * VM testbase keywords: [stress, slow, nonconcurrent, quick] - * VM testbase readme: - * DESCRIPTION - * This test transfers huge amount of data between 2 Java virtual machines - * using the TCP/IP protocol, and checks if those data are transfered correctly. - * Both client and server VMs run on the same local computer and attach TCP/IP - * sockets to the local host, or to the loopback domain ``localhost'' - * (having IP address 127.0.0.1). - * In this test, 128 client/server connections are established. Once a - * connection is established, client passes a large data parcel to server, - * and server reads that parcel and checks if it is same as expected - * (byte-to-byte equality is desired). Then server passes (some other) parcel - * to the client, and client reads and verifies those bytes. This ping-pong - * game is repeated 128 times; and after that each pair of sockets checks if - * there are no extra bytes accudentally passed through their connection. - * Parcels lengths and contents are chosen randomly, and average - * parcel length is 128 bytes. So totally, each pair of sockets passes ~16Kb of - * data to each other, and thus ~32Kb of data are transfered by each sockets - * pair. Totally, ~4Mb of data are transfered by all client/server pairs. - * COMMENTS - * The production Solaris_JDK_1.3-b12 Server VM intermittently crashes under - * this test, even when client part of the test is executed with Client HS: - * >>>> java -server network004 java - * # - * # HotSpot Virtual Machine Error, Unexpected Signal 10 - * # Please report this error at - * # http://java.sun.com/cgi-bin/bugreport.cgi - * # - * # Error ID: 4F533F534F4C415249530E43505007D9 01 - * # - * # Problematic Thread: prio=5 tid=0x214418 nid=0x103 runnable - * # - * (ErrorID == "os_solaris.cpp, 2009") - * If the client part of the test is executed with Server HS, the - * production Solaris_JDK_1.3-b12 Server VM intermittently fails - * this test due to timeout: - * >>>> time java -server network004 'java -server -showversion' - * java version "1.3" - * Java(TM) 2 Runtime Environment, Standard Edition (build Solaris_JDK_1.3-b12) - * Java HotSpot(TM) Server VM (build 1.3-b12, mixed mode) - * # Client #96: java.io.InterruptedIOException: Read timed out - * # Client VM has crashed: exit status=97 - * # Test failed. - * 156.0u 117.0s 7:06 63% 0+0k 0+0io 0pf+0w - * Test was fixed: - * added WAITTIME parameter defined timeout for TCP/IP sockets in minutes - * - * @library /vmTestbase - * /test/lib - * @run driver jdk.test.lib.FileInstaller . . - * @build nsk.stress.network.network004 - * @run main/othervm PropertyResolvingWrapper - * nsk.stress.network.network004 - * "${test.jdk}/bin/java ${test.vm.opts} ${test.java.opts}" 5 - */ - -package nsk.stress.network; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintStream; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.Random; -import java.util.StringTokenizer; - -/** - * This test transfers huge amount of data between 2 Java virtual machines - * using the TCP/IP protocol, and checks if those data are transfered correctly. - * Both client and server VMs run on the same local computer and attach TCP/IP - * sockets to the local host, or to the loopback domain ``localhost'' - * (having IP address 127.0.0.1). - *

- *

In this test, 128 client/server connections are established. Once a - * connection is established, client passes a large data parcel to server, - * and server reads that parcel and checks if it is same as expected - * (byte-to-byte equality is desired). Then server passes (some other) parcel - * to the client, and client reads and verifies those bytes. This ping-pong - * game is repeated 128 times; and after that each pair of sockets checks if - * there are no extra bytes accudentally passed through their connection. - *

- *

Parcels lengths and contents are chosen randomly, and average - * parcel length is 128 bytes. So totally, each pair of sockets passes ~16Kb of - * data to each other, and thus ~32Kb of data are transfered by each sockets - * pair. Totally, ~4Mb of data are transfered by all client/server pairs. - */ -public class network004 { - /** - * Timeout for TCP/IP sockets (currently set to 1 min). - */ - private static int SO_TIMEOUT;// = 2*60*1000; - - /** - * Maximal number of connections this test should open simultaneously. - */ - private final static int MAX_CONNECTIONS = 128; - - /** - * Check few more connections to make sure that MAX_CONNECTIONS are safe. - */ - private final static int CONNECTIONS_RESERVE = 10; - - /** - * Number of parcels to be sent/recieved. - */ - private final static int DATA_PARCELS = 128; - - /** - * Maximal length of data parcel to be sent/recieved - * (it equals to 256 bytes now). - */ - private final static int MAX_PARCEL = 1 << 8; - - /** - * Either actually display optional reports or not. - */ - static private final boolean DEBUG_MODE = false; - - /** - * How many IP sockets can we open simultaneously? - * Check if MAX_CONNECTIONS connections - * can be open simultaneously. - */ - private static int detectOSLimitation() { - final int CONNECTIONS_TO_TRY = MAX_CONNECTIONS + CONNECTIONS_RESERVE; - ServerSocket ssoc[] = new ServerSocket[CONNECTIONS_TO_TRY]; - display("--- Trying to open " + CONNECTIONS_TO_TRY + " connections:"); - int i; - for (i = 0; i < CONNECTIONS_TO_TRY; i++) - try { - ssoc[i] = new ServerSocket(0); - display("--- Open: ssoc[" + i + "] = " + ssoc[i]); - } catch (IOException ioe) { - display("--- OOPS! -- failed to open connection #" + i); - break; - } - display("--- Could open " + - (i < CONNECTIONS_TO_TRY ? "only " : "") + i + " connections."); - display("--- Closing them:"); - for (int j = 0; j < i; j++) - try { - ssoc[j].close(); - } catch (IOException ioe) { - throw new Error("FATAL error while loading the test: " + ioe); - } - display("--- OK."); - int safeConnections = i - CONNECTIONS_RESERVE; - if (safeConnections < 1) - safeConnections = 1; - if (safeConnections < MAX_CONNECTIONS) { - complain("------------------------- CAUTION: -------------------"); - complain("While checking the OS limitations, the test found that"); - complain("only " + i + " TCP/IP socket connections could be safely open"); - complain("simultaneously. However, possibility to open at least"); - complain("" + MAX_CONNECTIONS + "+" + CONNECTIONS_RESERVE - + " connections were expected."); - complain(""); - complain("So, the test will check only " + safeConnections + " connection" - + (safeConnections == 1 ? "" : "s") + " which seem"); - complain("safe to be open simultaneously."); - complain("------------------------------------------------------"); - } - return safeConnections; - } - - //----------------------------------------------------------------// - - /** - * Re-calls to the method run(args[],out) actually - * performing the test. After run(args[],out) stops, - * follow JDK-like convention for exit codes. I.e.: stop with - * exit status 95 if the test has passed, or with status 97 if - * the test has failed. - * - * @see #run(String[], PrintStream) - */ - public static void main(String args[]) { - int exitCode = run(args, System.out); - System.exit(exitCode + 95); - // JCK-like exit status. - } - - /** - * Parse command-line parameters stored into args[] array, - * then perform the test. I.e.: start the server thread at the same VM - * this method runs, then start the other client VM, and verify data - * transfer through TCP/IP connection between those different virtual - * machines. - *

- *

There should be 1 or 2 command-line parameters: - *
   - * java network004 java_command - * [IP-address | host_name | localhost ] - *
where parameters are: - *
   - * java_command - how to start java, - * e.g.: ``c:\jdk1.3\bin\java -classic'' - *
   - * waittime - timeout for TCP/IP sockets in minutes - *
   - * IP-address - local hots's address, or 127.0.0.1 - *
   - * host_name - local host's domain name, or the - * keyword ``localhost'' - *
   - * localhost - placeholder for the IP-address 127.0.0.1 - *

- *

Usually, java_command should point to the same - * Java machine just executing this test. However, every compatible Java 2 - * implementation is appropriate. - *

- *

If optional parameter is ommited, the test invokes the method - * InetAddress.getLocalHost() to get the domain name and - * IP-address of the local computer. - */ - public static int run(String args[], PrintStream out) { - network004.out = out; - - // - // Get the Internet address of the local machine. - // - InetAddress address = null; - try { - switch (args.length) { - case 2: - address = InetAddress.getLocalHost(); - break; - case 3: - address = InetAddress.getByName(args[2]); - break; - default: - complain("Illegal arguments number; execute:"); - complain(" java network004 $JAVA_COMMAND " + - "[$IP_ADDRESS | $HOST_NAME | localhost]"); - return 2; // FAILED - } - } catch (UnknownHostException exception) { - complain(exception.toString()); - return 2; // FAILED - } - display("Host: " + address); - - // - // Detect if it is safe to open MAX_CONNETIONS simultaneously: - // - final int CONNECTIONS = detectOSLimitation(); - - // - // Start the server thread on the same VM (which executes this method). - // - Server server[] = new Server[CONNECTIONS]; - for (int i = 0; i < CONNECTIONS; i++) { - try { - server[i] = new Server(address); - } catch (Exception exception) { - complain("Server #" + i + ": " + exception); - return 2; - } - display("Server #" + i + ": " + server[i]); - server[i].start(); - } - - // - // Start the client process on different VM. - // - String command = args[0] + " " + network004.class.getName() + "$Client"; - try { - SO_TIMEOUT = Integer.parseInt(args[1]) * 60 * 1000; - } catch (NumberFormatException e) { - complain("Wrong timeout argument: " + e); - return 2; - } - - Runtime runtime = Runtime.getRuntime(); - - Process client = null; - IORedirector redirectOut = null; - IORedirector redirectErr = null; - - try { - // Start clients on different JVM: - client = runtime.exec(command); - - // Provide clients with access to stderr and stdout: - InputStream clientOut = client.getInputStream(); - InputStream clientErr = client.getErrorStream(); - redirectOut = new IORedirector(clientOut, DEBUG_MODE ? out : null); - redirectErr = new IORedirector(clientErr, out); - redirectOut.start(); - redirectErr.start(); - - // Pass parameters to clients (number of connections, and IP adresses and ports): - PrintStream clientIn = new PrintStream(client.getOutputStream()); - clientIn.println(CONNECTIONS); - for (int i = 0; i < CONNECTIONS; i++) - clientIn.println(server[i].getIPAddress() + " " + server[i].getPort()); - clientIn.flush(); - clientIn.close(); - - } catch (Exception exception) { - complain("Failed to start client: " + exception); - return 2; - } - - // - // Wait until the server and client both stop. - // - boolean testFailed = false; - try { - client.waitFor(); - // Let I/O redirectors to flush: - if (redirectOut.isAlive()) - redirectOut.join(); - if (redirectErr.isAlive()) - redirectErr.join(); - - // If client has crashed, also terminate the server (to avoid hangup). - int clientStatus = client.exitValue(); - if (clientStatus != 95) { - complain("Client VM has failed: exit status=" + clientStatus); - testFailed = true; - } - - // Client has finished OK; wait for the server. - for (int i = 0; i < CONNECTIONS; i++) { - display("Server: waiting for #" + i); - while (server[i].isAlive()) - server[i].join(); - if (server[i].exception != null) { - complain("Server thread #" + i + ": " + server[i].exception); - testFailed = true; - } - } - - } catch (Exception exception) { - complain("Test interrupted: " + exception); - testFailed = true; - } - - if (testFailed) - complain("Test failed."); - else - display("Test passed."); - return testFailed ? 2 : 0; - } - - //----------------------------------------------------------------// - - /** - * Log stream for error messages and/or (optional) execution trace. - */ - private static PrintStream out; - - /** - * Print error message. - */ - private static synchronized void complain(Object message) { - out.println("# " + message); - out.flush(); - } - - /** - * Display optional report: comment ca va? - */ - private static synchronized void display(Object report) { - if (DEBUG_MODE) - out.println(report.toString()); - out.flush(); - } - - //----------------------------------------------------------------// - - /** - * Server thread should reply to data parcels sent by Client VM. - */ - private static class Server extends Thread { - /** - * The socket to listen for a client. - */ - private ServerSocket serverSocket; - - /** - * Display the server socket. - */ - public String toString() { - return serverSocket.toString(); - } - - /** - * Server's IP-address in the form ``x.y.u.z'', - * or ``127.0.0.1'' for loopback connection. - */ - public String getIPAddress() { - return serverSocket.getInetAddress().getHostAddress(); - } - - /** - * Which port is this socket listening? - */ - int getPort() { - return serverSocket.getLocalPort(); - } - - /** - * Find some free port at the given address - * and attach new server to hear that port. - */ - public Server(InetAddress address) throws IOException { - int someFreePort = 0; - int backlog = 50; // default for new ServerSocket(port) - serverSocket = new ServerSocket(someFreePort, backlog, address); - } - - /** - * Exception just arisen while the server was working, - * or null if it was OK with the server. - */ - Exception exception = null; - - /** - * Accept connection, then reply to client's parcels. - */ - public void run() { - try { - Socket socket = serverSocket.accept(); - socket.setSoTimeout(SO_TIMEOUT); -// display("Server: " + socket); - - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(getPort()); - - for (int i = 0; i < DATA_PARCELS; i++) { - Parcel etalon = new Parcel(random); - - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - complain("Server thread for port #" - + getPort() + " got unexpected parcel:\n" - + "sample=" + sample + "\n" - + "etalon=" + etalon); - throw new TestFailure( - "server has read unexpected parcel"); - } - - etalon.send(ostream); - ostream.flush(); - } - - int datum = istream.read(); // wait for client close() - if (datum >= 0) - throw new TestFailure( - "server has read ambigous byte: " + datum); - - ostream.close(); // implies: socket.close(); - - } catch (Exception oops) { - exception = oops; - } - } - - } - - //----------------------------------------------------------------// - - /** - * Client VM should send data parcels to Server VM and - * recieve and verify the server's replies. - */ - private static class Client extends Thread { - /** - * This thread uses the single client socket. - */ - private Socket socket; - - /** - * Address and port of this socket. - */ - public String toString() { - return socket.toString(); - } - - /** - * Did the thread failed? If yes, what is the failure's reason. - */ - Exception exception = null; - - /** - * Connect client socket on the given address - * and port. - */ - Client(InetAddress address, int port) throws IOException { - socket = new Socket(address, port); - socket.setSoTimeout(SO_TIMEOUT); - } - - /** - * What is the port number this socket is listening for? - */ - int getPort() { - return socket.getPort(); - } - - /** - * Establish connection, then read/respond DATA_PARCELS parcels - * of random data. Set initial seed for pseudo-random numbers generator - * to the value of the local port number. - * - * @see #DATA_PARCELS - * @see #getPort() - */ - public void run() { - try { - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(getPort()); - - for (int i = 0; i < DATA_PARCELS; i++) { - Parcel etalon = new Parcel(random); - etalon.send(ostream); - ostream.flush(); - - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - complain("Client thread for port #" - + getPort() + " got unexpected parcel:\n" - + "sample=" + sample + "\n" - + "etalon=" + etalon); - throw new TestFailure( - "parcel context is unexpected to client"); - } - } - - if (istream.available() > 0) { - int datum = istream.read(); - throw new TestFailure( - "client has read ambigous byte: " + datum); - } - ostream.close(); // implies: socket.close() - - } catch (Exception oops) { - exception = oops; - } - } - - /** - * Establish connections to lots of server sockets, atack servers with - * huge data parcels, and check if it replies correctly. The addresses - * and port numbers for server sockets are passed through stdin. - * The input stream must consist of the stipulated number (up to 128+1) of - * lines containing the pair of symbolic server domain name and the port number, - * like: - *
   actual_number_of_sockets - *
   address_1 port_1 - *
   address_2 port_2 - *
   . . . - *
   address_N port_N - *
where N must equal to the actual_number_of_sockets. - */ - public static void main(String args[]) { - // ---- Parse stdin for the list of server sockets: ---- // - BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); - - final int CONNECTIONS; - try { - String line = in.readLine(); - if (line == null) { - complain("Client expects paramenets passed through stdin:"); - complain(" actual_number_of_sockets"); - complain(" IP-address_1 port_1"); - complain(" IP-address_2 port_2"); - complain(" . . ."); - complain(" IP-address_N port_N"); - exit(2); // FAILED - } - CONNECTIONS = Integer.parseInt(line); - } catch (IOException ioe) { - complain("Client failed to read the actual number of CONNECTIONS"); - throw new RuntimeException(ioe.toString()); - } - - Client client[] = new Client[CONNECTIONS]; - for (int i = 0; i < CONNECTIONS; i++) - try { - String line = in.readLine(); - if (line == null) { - complain("Client: failed to read address/port for client #" + i); - exit(3); - } - - StringTokenizer tokenz = new StringTokenizer(line); - if (tokenz.countTokens() != 2) { - complain("Client: illegal input string: " + line); - exit(3); - } - String serverName = (String) tokenz.nextElement(); - InetAddress address = InetAddress.getByName(serverName); - int port = Integer.parseInt((String) tokenz.nextElement()); - - client[i] = new Client(address, port); - - display("Client #" + i + ": " + client[i]); - - } catch (IOException ioe) { - complain("Client #" + i + ": " + ioe); - exit(3); - } - - // ---- Start testing: ---- // - - for (int i = 0; i < CONNECTIONS; i++) - client[i].start(); - - int status = 0; - for (int i = 0; i < CONNECTIONS; i++) { - display("Client: waiting for #" + i); - while (client[i].isAlive()) - yield(); - if (client[i].exception != null) { - complain("Client #" + i + ": " + client[i].exception); - status = 2; - } - } - - exit(status); - } - - /** - * Print error message. - */ - private static synchronized void complain(Object message) { - System.err.println("# " + message); - System.err.flush(); - } - - /** - * Display execution trace. - */ - private static synchronized void display(Object message) { - if (!DEBUG_MODE) - return; - System.out.println(message.toString()); - System.out.flush(); - } - - /** - * Exit with JCK-like status. - */ - private static void exit(int exitCode) { - System.exit(exitCode + 95); - } - - } - - /** - * Two of such threads should redirect out and err - * streams of client VM. - */ - private static class IORedirector extends Thread { - /** - * Source stream. - */ - InputStream in; - /** - * Destination stream. - */ - OutputStream out; - - /** - * Redirect in to out. - */ - public IORedirector(InputStream in, OutputStream out) { - this.in = in; - this.out = out; - } - - /** - * Read input stream until the EOF, and write everithing to output stream. - * If output stream is assigned to null, do not print anything, - * but read the input stream anywhere. - */ - public void run() { - try { - for (; ; ) { - int symbol = in.read(); - if (symbol < 0) - break; // EOF - if (out != null) - out.write(symbol); - } - - if (out != null) - out.flush(); - - } catch (Exception exception) { - throw new TestFailure("IORedirector exception: " + exception); - } - } - } - - //----------------------------------------------------------------// - - /** - * A data parcel to be sent/recieved between Client VM and Server thread. - * When data parcel is sent, first 4 bytes are transfered which encode the - * int number equal to size of the parcel minus 1. I.e.: if - * number of data bytes in the parcel's contents is N, then - * the first 4 bytes encode the number N-1. After that, the - * parcel's contents bytes are transered. - */ - static class Parcel { - private byte[] parcel; - - /** - * Display all bytes as integer values from 0 to 255; - * or return ``null'' if this Parcel is not - * yet initialized. - */ - public String toString() { - if (parcel == null) - return "null"; - String s = "{"; - for (int i = 0; i < parcel.length; i++) - s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF); - return s + "}"; - } - - /** - * Generate new parcel[] array using the given - * random numbers generator. Client and Server - * threads should use identical random generators, - * so that those threads could generate equal data parcels and - * check the parcel just transfered. - */ - public Parcel(Random random) { - int size = random.nextInt(MAX_PARCEL) + 1; - parcel = new byte[size]; - for (int i = 0; i < size; i++) - parcel[i] = (byte) random.nextInt(256); - } - - /** - * Read exactly size bytes from the istream - * if possible, or throw TestFailure if unexpected end of - * istream occurs. - */ - private static byte[] readBytes(int size, InputStream istream) - throws IOException { - - byte data[] = new byte[size]; - for (int i = 0; i < size; i++) { - int datum = istream.read(); - if (datum < 0) - throw new TestFailure( - "unexpected EOF: have read: " + i + " bytes of " + size); - data[i] = (byte) datum; - } - return data; - } - - /** - * Read 4 bytes from istream and threat them to encode - * size of data parcel following these 4 bytes. - */ - private static int getSize(InputStream istream) throws IOException { - byte data[] = readBytes(4, istream); - int data0 = (int) data[0] & 0xFF; - int data1 = (int) data[1] & 0xFF; - int data2 = (int) data[2] & 0xFF; - int data3 = (int) data[3] & 0xFF; - int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24); - int size = sizeWord + 1; - if (size <= 0) - throw new TestFailure("illegal size: " + size); - return size; - } - - /** - * Send 4 bytes encoding actual size of the parcel just to be transfered. - */ - private static void putSize(OutputStream ostream, int size) - throws IOException { - - if (size <= 0) - throw new TestFailure("illegal size: " + size); - - int sizeWord = size - 1; - byte data[] = new byte[4]; - data[0] = (byte) sizeWord; - data[1] = (byte) (sizeWord >> 8); - data[2] = (byte) (sizeWord >> 16); - data[3] = (byte) (sizeWord >> 24); - ostream.write(data); - } - - /** - * Recieve data parcel. - */ - public Parcel(InputStream istream) throws IOException { - int size = getSize(istream); - parcel = readBytes(size, istream); - } - - /** - * Send this data parcel. - */ - public void send(OutputStream ostream) throws IOException { - int size = parcel.length; - putSize(ostream, size); - ostream.write(parcel); - } - - /** - * Check byte-to-byte equality between this and the - * other parcels. - */ - public boolean equals(Parcel other) { - if (this.parcel.length != other.parcel.length) - return false; - int size = parcel.length; - for (int i = 0; i < size; i++) - if (this.parcel[i] != other.parcel[i]) - return false; - return true; - } - - } - - /** - * Server or Client may throw this exception to report the test failure. - */ - static class TestFailure extends RuntimeException { - /** - * Report particular purpose of the test failure. - */ - public TestFailure(String purpose) { - super(purpose); - } - - } - -} diff -r 4fd8872aebb4 -r 24ca55b8deed test/hotspot/jtreg/vmTestbase/nsk/stress/network/network005.java --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/network/network005.java Wed Dec 05 20:59:55 2018 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,635 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* - * @test - * @key stress - * - * @summary converted from VM testbase nsk/stress/network/network005. - * VM testbase keywords: [stress, slow, nonconcurrent, quick] - * VM testbase readme: - * DESCRIPTION - * This test make huge number of data transers between one server and - * multiple clients communicating via TCP/IP sockets, and checks if those - * data are transfered correctly. All TCP/IP sockets are attached to local - * host (by its domain name), or to the ``localhost'' loopback (having the - * IP address 127.0.0.1). - * In this test, 128 client/server connections are established. Once a - * connection is established, client passes a large data parcel to server, - * and server reads that parcel and checks if it is same as expected - * (byte-to-byte equality is desired). Then server passes (some other) parcel - * to the client, and client reads and verifies those bytes. This ping-pong - * game is repeated 128 times; and after that each pair of sockets checks if - * there are no extra bytes accudentally passed through their connection. - * Parcels lengths and contents are chosen randomly, and average parcel - * length is 128 bytes. So totally, each pair of sockets passes ~16Kb of - * data to each other, and thus ~32Kb of data are transfered by each sockets - * pair. Totally, ~4Mb of data are transfered by all client/server pairs. - * COMMENTS - * - * @run main/othervm nsk.stress.network.network005 - */ - -package nsk.stress.network; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.Random; - -/** - * This test make huge number of data transers between one server and - * multiple clients communicating via TCP/IP sockets, and checks if those - * data are transfered correctly. All TCP/IP sockets are attached to local - * host (by its domain name), or to the ``localhost'' loopback (having the - * IP address 127.0.0.1). - *

- *

In this test, 128 client/server connections are established. Once a - * connection is established, client passes a large data parcel to server, - * and server reads that parcel and checks if it is same as expected - * (byte-to-byte equality is desired). Then server passes (some other) parcel - * to the client, and client reads and verifies those bytes. This ping-pong - * game is repeated 128 times; and after that each pair of sockets checks if - * there are no extra bytes accudentally passed through their connection. - *

- *

Parcels lengths and contents are chosen randomly, and average parcel - * length is 128 bytes. So totally, each pair of sockets passes ~16Kb of - * data to each other, and thus ~32Kb of data are transfered by each sockets - * pair. Totally, ~4Mb of data are transfered by all client/server pairs. - */ -public class network005 { - /** - * Do actually display optional reports? - */ - static private final boolean DEBUG_MODE = false; - - /** - * Errors and optional reports log. Usually System.out. - */ - static private PrintStream out = System.out; - - /** - * Print error message: all clients and servers may print concurently. - */ - static private synchronized void println(Object message) { - out.println(message.toString()); - } - - /** - * Display optional report: comment ca va. - */ - static private void display(Object report) { - if (DEBUG_MODE) - println(report.toString()); - } - - /** - * Maximal number of connections this test should open simultaneously. - */ - private final static int MAX_CONNECTIONS = 128; - - /** - * Check few more connections to make sure that MAX_CONNECTIONS are safe. - */ - private final static int CONNECTIONS_RESERVE = 10; - - /** - * Number of client/server connections to establish. - */ - private static final int CONNECTIONS = detectOSLimitation(); - - /** - * Number of parcels to be sent/recieved. - */ - private static final int DATA_PARCELS = 128; - - /** - * Maximal length of data parcel to be sent/recieved - * (it equals to 256 bytes now). - */ - private static final int MAX_PARCEL = 1 << 8; - - /** - * How many IP sockets can we open simultaneously? - * Check if MAX_CONNECTIONS connections - * can be open simultaneously. - */ - private static int detectOSLimitation() { - final int CONNECTIONS_TO_TRY = MAX_CONNECTIONS + CONNECTIONS_RESERVE; - display("--- Trying to open " + CONNECTIONS_TO_TRY + " connections:"); - - InetAddress address; - ServerSocket serverSocket; - try { - address = InetAddress.getLocalHost(); - int anyPort = 0; - int defaultBacklog = 50; - serverSocket = new ServerSocket(anyPort, defaultBacklog, address); - } catch (IOException ioe) { - throw new Error("FATAL error while loading the test: " + ioe); - } - display(serverSocket.toString()); - - Socket server[] = new Socket[CONNECTIONS_TO_TRY]; - Socket client[] = new Socket[CONNECTIONS_TO_TRY]; - - int i, port = serverSocket.getLocalPort(); - for (i = 0; i < CONNECTIONS_TO_TRY; i++) - try { - client[i] = new Socket(address, port); - display("--- Open: client[" + i + "] = " + client[i]); - server[i] = serverSocket.accept(); - display("--- Open: server[" + i + "] = " + server[i]); - } catch (IOException ioe) { - display("--- OOPS! -- failed to open connection #" + i); - break; - } - display("--- Could open " + - (i < CONNECTIONS_TO_TRY ? "only " : "") + i + " connections."); - display("--- Closing them:"); - for (int j = 0; j < i; j++) - try { - server[j].close(); - client[j].close(); - } catch (IOException ioe) { - throw new Error("FATAL error while loading the test: " + ioe); - } - display("--- OK."); - int safeConnections = i - CONNECTIONS_RESERVE; - if (safeConnections < 1) - safeConnections = 1; - if (safeConnections < MAX_CONNECTIONS) { - println("# ------------------------- CAUTION: -------------------"); - println("# While checking the OS limitations, the test found that"); - println("# only " + i + " TCP/IP socket connections could be safely open"); - println("# simultaneously. However, possibility to open at least"); - println("# " + MAX_CONNECTIONS + "+" + CONNECTIONS_RESERVE - + " connections were expected."); - println("# "); - println("# So, the test will check only " + safeConnections + " connection" - + (safeConnections == 1 ? "" : "s") + " which seem"); - println("# safe to be open simultaneously."); - println("# ------------------------------------------------------"); - } - return safeConnections; - } - - /** - * Server (or client) thread intended to transfer data parcels to - * another client (or server) Agent. - */ - static private class Agent extends Thread { - /** - * Agent's client mode. - */ - final static int CLIENT = 1; - /** - * Agen's server mode. - */ - final static int SERVER = 2; - - /** - * Is this agent is client or server one? - */ - private int mode; - - /** - * This server thread listens the single socket. - */ - private Socket socket; - - /** - * What is the port number this socket is listening for? - */ - int getPort() { - if (mode == SERVER) - return socket.getLocalPort(); - else - return socket.getPort(); - } - - /** - * Address and port of this server socket. - */ - public String toString() { - String mode = (this.mode == CLIENT) ? "Client" : "Server"; - return mode + ": " + socket.toString(); - } - - /** - * Did the thread failed? If yes, what is the failure's reason. - */ - Exception exception = null; - - /** - * Find some free port at the given address - * and attach new server to hear that port. - */ - Agent(Socket socket, int mode) { - if ((mode != SERVER) && (mode != CLIENT)) - throw new IllegalArgumentException("unknown mode=" + mode); - this.socket = socket; - this.mode = mode; - } - - /** - * Transfer DATA_PARCELS parcels of random data. - * Set initial seed for pseudo-random numbers generator - * to the value of the local port number. - * - * @see #DATA_PARCELS - * @see #getPort() - */ - public void run() { - try { - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(getPort()); - - for (int i = 0; i < DATA_PARCELS; i++) { - Parcel etalon = new Parcel(random); - - if (mode == SERVER) { - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - println("Server agent for port #" - + getPort() + " got unexpected parcel:\n" - + "sample=" + sample + "\n" - + "etalon=" + etalon); - throw new TestFailure( - "server has read unexpected parcel"); - } - - etalon.send(ostream); // reply - ostream.flush(); - - } else { - etalon.send(ostream); // init transfer - ostream.flush(); - - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - println("Client agent for port #" - + getPort() + " got unexpected parcel:\n" - + "sample=" + sample + "\n" - + "etalon=" + etalon); - throw new TestFailure( - "parcel context is unexpected to client"); - } - } - } - - if (mode == SERVER) { - int datum = istream.read(); // wait until client's close() - if (datum >= 0) - throw new TestFailure( - "server has read ambigous byte: " + datum); - - ostream.close(); // implies: socket.close(); - - } else { - if (istream.available() > 0) { - int datum = istream.read(); - throw new TestFailure( - "client has read ambigous byte: " + datum); - } - ostream.close(); // implies: socket.close() - } - - } catch (Exception oops) { - exception = oops; - } - } - - } - - /** - * A data parcel to sent/recieved between Client and Server threads. - * When data parcel is sent, first 4 bytes transfered encode the size - * of the parcel (i.e.: number of data bytes in the parcel's contents). - * Then the parcel's contents bytes are transered. - */ - static class Parcel { - private byte[] parcel; - - /** - * Display all bytes as integer values from 0 to 255; - * or return ``null'' if this Parcel is not - * yet initialized. - */ - public String toString() { - if (parcel == null) - return "null"; - String s = "{"; - for (int i = 0; i < parcel.length; i++) - s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF); - return s + "}"; - } - - /** - * Generate new parcel[] array using the given - * random numbers generator. Client and Server - * threads should use identical random generators, - * so that those threads could generate equal data parcels and - * check the parcel just transfered. - */ - public Parcel(Random random) { - int size = random.nextInt(MAX_PARCEL) + 1; - parcel = new byte[size]; - for (int i = 0; i < size; i++) - parcel[i] = (byte) random.nextInt(256); - } - - /** - * Read exactly size bytes from the istream - * if possible, or throw TestFailure if unexpected end of - * istream occurs. - */ - private static byte[] readBytes(int size, InputStream istream) - throws IOException { - - byte data[] = new byte[size]; - for (int i = 0; i < size; i++) { - int datum = istream.read(); - if (datum < 0) - throw new TestFailure( - "unexpected EOF: have read: " + i + " bytes of " + size); - data[i] = (byte) datum; - } - return data; - } - - /** - * Read 4 bytes from istream and threat them to encode - * size of data parcel following these 4 bytes. - */ - private static int getSize(InputStream istream) throws IOException { - byte data[] = readBytes(4, istream); - int data0 = (int) data[0] & 0xFF; - int data1 = (int) data[1] & 0xFF; - int data2 = (int) data[2] & 0xFF; - int data3 = (int) data[3] & 0xFF; - int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24); - int size = sizeWord + 1; - if (size <= 0) - throw new TestFailure("illegal size: " + size); - return size; - } - - /** - * Send 4 bytes encoding actual size of the parcel just to be transfered. - */ - private static void putSize(OutputStream ostream, int size) - throws IOException { - - if (size <= 0) - throw new TestFailure("illegal size: " + size); - - int sizeWord = size - 1; - byte data[] = new byte[4]; - data[0] = (byte) sizeWord; - data[1] = (byte) (sizeWord >> 8); - data[2] = (byte) (sizeWord >> 16); - data[3] = (byte) (sizeWord >> 24); - ostream.write(data); - } - - /** - * Recieve data parcel. - */ - public Parcel(InputStream istream) throws IOException { - int size = getSize(istream); - parcel = readBytes(size, istream); - } - - /** - * Send this data parcel. - */ - public void send(OutputStream ostream) throws IOException { - int size = parcel.length; - putSize(ostream, size); - ostream.write(parcel); - } - - /** - * Check byte-to-byte equality between this and the - * other parcels. - */ - public boolean equals(Parcel other) { - if (this.parcel.length != other.parcel.length) - return false; - int size = parcel.length; - for (int i = 0; i < size; i++) - if (this.parcel[i] != other.parcel[i]) - return false; - return true; - } - - } - - /** - * Server or Client thread may throw this exception to report the test - * failure. - */ - static class TestFailure extends RuntimeException { - /** - * Report particular purpose of the test failure. - */ - public TestFailure(String purpose) { - super(purpose); - } - - } - - /** - * Attach client and server sockets to the local host, and check if - * huge number of data transfers could be correctly transfered between - * these sockets. - *

- *

Command-line parameters provided with args[] may - * prompt the local host IP address or domain name. Execute: - *
   - * java network005 [IP-address | host_name | - * localhost ] - *
where parameters are: - *
   - * IP-address - local hots's address, or 127.0.0.1 - *
   - * host_name - local host's domain name, or the - * keyword ``localhost'' - *
   - * localhost - placeholder for the IP-address 127.0.0.1 - *
By default, the test uses the Internet address available via - * the method InetAddress.getLocalHost() - */ - public static int run(String args[], PrintStream out) { - network005.out = out; - - // - // Get IP address of the local machine. - // - - InetAddress address = null; - try { - switch (args.length) { - case 0: - address = InetAddress.getLocalHost(); - break; - case 1: - String hostName = args[0]; - address = InetAddress.getByName(args[0]); - break; - default: - println("Use:"); - println(" java network005"); - println("or:"); - println(" java network005 ${IP_ADDRESS}"); - println("or:"); - println(" java network005 ${HOST_NAME}"); - println("or:"); - println(" java network005 localhost"); - return 2; // FAILED - } - } catch (UnknownHostException exception) { - println(exception); - return 2; // FAILED - } - display("Host: " + address); - - // - // Assign ServerSocket to the local host: - // - - ServerSocket serverSocket; - try { - final int anyPort = 0; - final int defaultBacklog = 50; - serverSocket = new ServerSocket(anyPort, defaultBacklog, address); - } catch (IOException ioe) { - println("# Failed to assign ServerSocket on: " + address); - return 2; - } - display(serverSocket.toString()); - - final int port = serverSocket.getLocalPort(); - - // - // Incarnate the server & the client agents. - // - - Agent server[] = new Agent[CONNECTIONS]; - Agent client[] = new Agent[CONNECTIONS]; - - for (int i = 0; i < CONNECTIONS; i++) - try { - Socket socket; - socket = new Socket(address, port); - client[i] = new Agent(socket, Agent.CLIENT); - display("Client #" + i + ": " + socket); - socket = serverSocket.accept(); - server[i] = new Agent(socket, Agent.SERVER); - display("Server #" + i + ": " + socket); - } catch (IOException io) { - println("Failed establish conection #" + i + ": " + io); - return 2; - } - - // - // Execute the server and client threads. - // - - Exception exception = null; - for (int i = 0; i < CONNECTIONS; i++) { - server[i].start(); - client[i].start(); - } - try { - boolean someIsAlive = true; - while (someIsAlive) { - boolean aliveFound = false; - boolean someBroken = false; - for (int i = 0; i < CONNECTIONS; i++) - if (client[i].isAlive() || server[i].isAlive()) { - if ((client[i].exception != null) || - (server[i].exception != null)) - someBroken = true; - aliveFound = true; - Thread.yield(); - } - someIsAlive = aliveFound; - if (someBroken) - break; - } - } catch (TestFailure failure) { - exception = failure; - } - - // Failure diagnostics, if needed. - - Exception problem[] = new Exception[2 * CONNECTIONS + 1]; - problem[0] = exception; - for (int i = 0; i < CONNECTIONS; i++) { - problem[2 * i + 1] = server[i].exception; - problem[2 * i + 2] = client[i].exception; - } - - int exitCode = 0; - - for (int i = 0; i < 2 * CONNECTIONS + 1; i++) - if (problem[i] != null) { - out.println("#### OOPS ! ####"); - problem[i].printStackTrace(out); - exitCode = 2; - } - - if (exitCode != 0) { - out.println("#### OOPS ! ####"); - out.println("# Test failed."); - return 2; // FAILED - } - display("Test passed."); - return 0; // PASSED - } - - /** - * Re-calls to the method run(args[],out) actually - * performing the test; and stop with exit code 95 if the test - * has passed, or with code 97 if the test has failed. - * (This is JCK-like exit codes convention.) - * - * @see #run(String[], PrintStream) - */ - public static void main(String args[]) { - int exitCode = run(args, System.out); - System.exit(exitCode + 95); - // JCK-like exit code. - } - -} diff -r 4fd8872aebb4 -r 24ca55b8deed test/hotspot/jtreg/vmTestbase/nsk/stress/network/network006.java --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/network/network006.java Wed Dec 05 20:59:55 2018 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,916 +0,0 @@ -/* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* - * @test - * @key stress - * - * @summary converted from VM testbase nsk/stress/network/network006. - * VM testbase keywords: [stress, slow, nonconcurrent, quick, quarantine] - * VM testbase comments: 8185072 - * VM testbase readme: - * DESCRIPTION - * This test makes huge number of data transfers between 2 Java virtual - * machines using the TCP/IP protocol, and checks if those data are transfered - * correctly. Both client and server VMs run on the same local computer and - * attach TCP/IP sockets to the local host, or to the loopback domain - * ``localhost'' (having IP address 127.0.0.1). - * In this test, 128 client/server connections are established. Once a - * connection is established, client passes a data parcel to server, and server - * reads that parcel and checks if it is same as expected (byte-to-byte equality - * is desired). Then server passes (some other) parcel to the client, and client - * reads and verifies those bytes. This ping-pong game is repeated 128 times; and - * after that each pair of sockets checks if there are no extra bytes accudentally - * passed through their connection. - * Parcels lengths and contents are chosen randomly, and average parcel length - * is 128 bytes. So totally, each pair of sockets passes ~16Kb of data to each other, - * and thus ~32Kb of data are transfered by each sockets pair. Totally, ~4Mb of data - * are transfered by all client/server pairs. - * COMMENTS - * Test was fixed: - * added WAITTIME parameter defined timeout for TCP/IP sockets in minutes - * - * @library /vmTestbase - * /test/lib - * @run driver jdk.test.lib.FileInstaller . . - * @build nsk.stress.network.network006 - * @run main/othervm PropertyResolvingWrapper - * nsk.stress.network.network006 - * "${test.jdk}/bin/java ${test.vm.opts} ${test.java.opts}" 5 - */ - -package nsk.stress.network; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.Random; - -/** - * This test makes huge number of data transfers between 2 Java virtual - * machines using the TCP/IP protocol, and checks if those data are transfered - * correctly. Both client and server VMs run on the same local computer and - * attach TCP/IP sockets to the local host, or to the loopback domain - * ``localhost'' (having IP address 127.0.0.1). - *

- *

In this test, 128 client/server connections are established. Once a - * connection is established, client passes a data parcel to server, and server - * reads that parcel and checks if it is same as expected (byte-to-byte equality - * is desired). Then server passes (some other) parcel to the client, and client - * reads and verifies those bytes. This ping-pong game is repeated 128 times; and - * after that each pair of sockets checks if there are no extra bytes accudentally - * passed through their connection. - *

- *

Parcels lengths and contents are chosen randomly, and average parcel length - * is 128 bytes. So totally, each pair of sockets passes ~16Kb of data to each other, - * and thus ~32Kb of data are transfered by each sockets pair. Totally, ~4Mb of data - * are transfered by all client/server pairs. - */ -public class network006 { - /** - * Timeout for TCP/IP sockets (currently set to 1 min). - */ - private static int SO_TIMEOUT;// = 2*60*1000; - - /** - * Maximal number of connections this test should open simultaneously. - */ - private final static int MAX_CONNECTIONS = 128; - - /** - * Check few more connections to make sure that MAX_CONNECTIONS are safe. - */ - private final static int CONNECTIONS_RESERVE = 10; - - /** - * The test used to fail with connection reset by peer set to 50. - * (and once in a three if it was set to 10). - * So now we set it to MAX_CONNECTIONS (128). - */ - private final static int BACKLOG_QUEUE_LENGTH = MAX_CONNECTIONS; - - /** - * Number of parcels to be sent/recieved. - */ - private final static int DATA_PARCELS = 128; - - /** - * Maximal length of data parcel to be sent/recieved - * (it equals to 256 bytes now). - */ - private final static int MAX_PARCEL = 1 << 8; - - /** - * Either actually display optional reports or not. - */ - static private final boolean DEBUG_MODE = false; - - /** - * How many IP sockets can we open simultaneously? - * Check if MAX_CONNECTIONS connections - * can be open simultaneously. - */ - private static int detectOSLimitation() { - final int CONNECTIONS_TO_TRY = MAX_CONNECTIONS + CONNECTIONS_RESERVE; - display("--- Trying to open " + CONNECTIONS_TO_TRY + " connections:"); - - InetAddress address; - ServerSocket serverSocket; - try { - address = InetAddress.getLocalHost(); - int anyPort = 0; - int defaultBacklog = BACKLOG_QUEUE_LENGTH; - serverSocket = new ServerSocket(anyPort, defaultBacklog, address); - } catch (IOException ioe) { - throw new Error("FATAL error while loading the test: " + ioe); - } - display(serverSocket.toString()); - - Socket server[] = new Socket[CONNECTIONS_TO_TRY]; - Socket client[] = new Socket[CONNECTIONS_TO_TRY]; - - int i, port = serverSocket.getLocalPort(); - for (i = 0; i < CONNECTIONS_TO_TRY; i++) - try { - client[i] = new Socket(address, port); - display(">Open: client[" + i + "] = " + client[i]); - server[i] = serverSocket.accept(); - display(">Open: server[" + i + "] = " + server[i]); - } catch (IOException ioe) { - display(">OOPS! -- failed to open connection #" + i); - break; - } - display("> Could open " + - (i < CONNECTIONS_TO_TRY ? "only " : "") + i + " connections."); - display(">Closing them:"); - for (int j = 0; j < i; j++) - try { - server[j].close(); - client[j].close(); - } catch (IOException ioe) { - throw new Error("FATAL error while loading the test: " + ioe); - } - display(">OK."); - int safeConnections = i - CONNECTIONS_RESERVE; - if (safeConnections < 1) - safeConnections = 1; - if (safeConnections < MAX_CONNECTIONS) { - complain("------------------------- CAUTION: -------------------"); - complain("While checking the OS limitations, the test found that"); - complain("only " + i + " TCP/IP socket connections could be safely open"); - complain("simultaneously. However, possibility to open at least"); - complain("" + MAX_CONNECTIONS + "+" + CONNECTIONS_RESERVE - + " connections were expected."); - complain(""); - complain("So, the test will check only " + safeConnections + " connection" - + (safeConnections == 1 ? "" : "s") + " which seem"); - complain("safe to be open simultaneously."); - complain("------------------------------------------------------"); - } - return safeConnections; - } - - //----------------------------------------------------------------// - - /** - * Re-calls to the method run(args[],out) actually - * performing the test. After run(args[],out) stops, - * follow JDK-like convention for exit codes. I.e.: stop with - * exit status 95 if the test has passed, or with status 97 if - * the test has failed. - * - * @see #run(String[], PrintStream) - */ - public static void main(String args[]) { - int exitCode = run(args, System.out); - System.exit(exitCode + 95); - // JCK-like exit status. - } - - /** - * Parse command-line parameters stored into args[] array, - * then perform the test. I.e.: start the server thread at the same VM - * this method runs, then start the other client VM, and verify data - * transfer through TCP/IP connection between those different virtual - * machines. - *

- *

There should be 2 or 3 command-line parameters: - *
   - * java network006 java_command - * [IP-address | host_name | localhost ] - *
where parameters are: - *
   - * java_command - how to start java, - * e.g.: ``c:\jdk1.3\bin\java -classic'' - *
   - * waittime - timeout for TCP/IP sockets in minutes - *
   - * IP-address - local hots's address, or 127.0.0.1 - *
   - * host_name - local host's domain name, or the - * keyword ``localhost'' - *
   - * localhost - placeholder for the IP-address 127.0.0.1 - *

- *

Usually, java_command should point to the same - * Java machine just executing this test. However, every compatible Java 2 - * implementation is appropriate. - *

- *

If optional parameter is ommited, the test invokes the method - * InetAddress.getLocalHost() to get the domain name and - * IP-address of the local computer. - */ - public static int run(String args[], PrintStream out) { - network006.out = out; - - // - // Get the Internet address of the local machine. - // - InetAddress address = null; - try { - switch (args.length) { - case 2: - address = InetAddress.getLocalHost(); - break; - case 3: - address = InetAddress.getByName(args[2]); - break; - default: - complain("Illegal arguments number; execute:"); - complain(" java " + network006.class.getName() + " $JAVA_COMMAND " + - "[$IP_ADDRESS | $HOST_NAME | localhost]"); - return 2; // FAILED - } - } catch (UnknownHostException exception) { - complain(exception.toString()); - return 2; // FAILED - } - display("Host: " + address); - - // - // Detect if it is safe to open MAX_CONNETIONS simultaneously: - // - final int CONNECTIONS = detectOSLimitation(); - - // - // Assign ServerSocket, and start client VM which should open - // the prescribed number of CONNECTIONS to that ServerSocket. - // - - ServerSocket serverSocket; - try { - final int anyPort = 0; - final int defaultBacklog = BACKLOG_QUEUE_LENGTH; - serverSocket = new ServerSocket(anyPort, defaultBacklog, address); - } catch (IOException exception) { - complain("Cannot assign a ServerSocket on: " + address); - return 2; - } - - // - // Start the client process on different VM. - // - - String IPAddress = address.getHostAddress(); - int localPort = serverSocket.getLocalPort(); - String arguments = " " + CONNECTIONS + " " + IPAddress + " " + localPort; - //String command = args[0] + " " + network006.class.getName() + "$Client " + arguments; - String command = args[0] + " " + Client.class.getName() + " " + arguments; - try { - SO_TIMEOUT = Integer.parseInt(args[1]) * 60 * 1000; - } catch (NumberFormatException e) { - complain("Wrong timeout argument: " + e); - return 2; - } - - Runtime runtime = Runtime.getRuntime(); - - Process client = null; - IORedirector redirectOut = null; - IORedirector redirectErr = null; - - try { - // Start clients on different JVM: - client = runtime.exec(command); - - // Provide clients with access to stderr and stdout: - InputStream clientOut = client.getInputStream(); - InputStream clientErr = client.getErrorStream(); - redirectOut = new IORedirector(clientOut, DEBUG_MODE ? out : null); - redirectErr = new IORedirector(clientErr, out); - redirectOut.start(); - redirectErr.start(); - - } catch (Exception exception) { - complain("Failed to start client: " + exception); - return 2; - } - // - // Start the server threads (and let them establish connections): - // - - Server server[] = new Server[CONNECTIONS]; - for (int i = 0; i < CONNECTIONS; i++) { - server[i] = new Server(serverSocket); - display("Server #" + i + ": " + server[i]); - server[i].start(); - } - - // - // Wait for the servers and the clients: - // - - boolean testFailed = false; - - try { - client.waitFor(); - int clientStatus = client.exitValue(); - display("Client VM exitCode=" + clientStatus); - - // Let I/O redirectors to flush: - if (redirectOut.isAlive()) - redirectOut.join(); - if (redirectErr.isAlive()) - redirectErr.join(); - - // If client has crashed, also terminate the server (to avoid hangup). - if (clientStatus != 95) { - complain("Client VM has crashed: exit status=" + clientStatus); - testFailed = true; - } - - // Client has finished OK; wait for the server. - for (int i = 0; i < CONNECTIONS; i++) { - display("Server: waiting for #" + i); - if (server[i].isAlive()) { - display("Server #" + i + ": (joining...)" + server[i]); - server[i].join(); - } - if (server[i].exception != null) { - if (server[i].message != null) - complain("Server #" + i + "(finished): with message:" + server[i].message); - - complain("Server #" + i + "(finished): " + server[i].exception); - server[i].exception.printStackTrace(out); - out.flush(); -// complain("Server #"+i+": "+server[i].exception.getStackTrace()); - testFailed = true; - } - } - - } catch (Exception exception) { - complain("Test interrupted: " + exception); - testFailed = true; - } - - if (testFailed) - complain("Test failed."); - else - display("Test passed."); - return testFailed ? 2 : 0; - } - - //----------------------------------------------------------------// - - /** - * Log stream for error messages and/or (optional) execution trace. - */ - private static PrintStream out; - - /** - * Print error message. - */ - private static synchronized void complain(Object message) { - out.println("# " + message); - out.flush(); - } - - /** - * Display optional report: comment ca va? - */ - private static synchronized void display(Object report) { - if (DEBUG_MODE) - out.println(report.toString()); - out.flush(); //todo shouldn't this be inside if?? - } - - //----------------------------------------------------------------// - - /** - * Server thread should reply to data parcels sent by Client VM. - */ - private static class Server extends Thread { - /** - * The socket is assigned at the Server instantiation. - */ - private ServerSocket serverSocket; - - /** - * The socket is assigned at the Server runtime. - */ - private Socket socket; - - /** - * Display the server socket. - */ - public String toString() { - - return "ServerSocket: " + serverSocket.toString(); -// + " socket: " + socket.toString(); - } - - /** - * Which port is this socket listening? - */ - int getPort() { - return serverSocket.getLocalPort(); - } - - /** - * Find some free port at the given address - * and attach new server to hear that port. // lidsten to?? - */ - public Server(ServerSocket serverSocket) { - this.serverSocket = serverSocket; - } - - /** - * Exception just arisen while the server was working, - * or null if it was OK with the server. - */ - Exception exception = null; - String message = null; - - /** - * Accept connection, then reply to client's parcels. - */ - public void run() { - try { - socket = serverSocket.accept(); - socket.setSoTimeout(SO_TIMEOUT); - - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(getPort()); - - for (int i = 0; i < DATA_PARCELS; i++) { - Parcel etalon = new Parcel(random); - message = "reading parcel number " + i; - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - complain("Server thread for port #" - + getPort() + " got unexpected parcel:\n" - + "sample=" + sample + "\n" - + "etalon=" + etalon); - throw new TestFailure( //received?? - "server has read unexpected parcel"); - } - message = "sending parcel number " + i; - etalon.send(ostream); - ostream.flush(); - } - - int datum = istream.read(); // wait for client close() - if (datum >= 0) - throw new TestFailure( - "server has read ambigous byte: " + datum); - - ostream.close(); // implies: socket.close(); - - } catch (Exception oops) { - exception = oops; - } - } - } - - //----------------------------------------------------------------// - - /** - * Client VM should send data parcels to Server VM and - * recieve and verify the server's replies. - */ - private static class Client extends Thread { - /** - * This thread uses the single client socket. - */ - private Socket socket; - - /** - * Address and port of this socket. - */ - public String toString() { - return socket.toString(); - } - - /** - * Did the thread failed? If yes, what is the failure's reason. - */ - Exception exception = null; - String message = null; - - - public static java.io.PrintStream complainStream = System.out; - public static java.io.PrintStream displayStream = System.err; - - /** - * Connect client socket on the given address - * and port. - */ - Client(InetAddress address, int port) throws IOException { - socket = new Socket(address, port); - socket.setSoTimeout(SO_TIMEOUT); - } - - /** - * What is the port number this socket is listening for? - */ - int getPort() { - return socket.getPort(); - } - - /** - * Establish connection, then read/respond DATA_PARCELS parcels - * of random data. Set initial seed for pseudo-random numbers generator - * to the value of the local port number. - * - * @see #DATA_PARCELS - * @see #getPort() - */ - public void run() { - try { - InputStream istream = socket.getInputStream(); - OutputStream ostream = socket.getOutputStream(); - - Random random = new Random(getPort()); - // suggested by Oleg -- to avoid race conditions - /* try{ - Thread.sleep(500); - } - catch (java.lang.InterruptedException e) - { - }*/ - - for (int i = 0; i < DATA_PARCELS; i++) { - Parcel etalon = new Parcel(random); - message = "sending parcel number: " + i; - etalon.send(ostream); - ostream.flush(); - - message = "reading parcel number: " + i; - Parcel sample = new Parcel(istream); // read - if (!sample.equals(etalon)) { - complain("Client thread for port #" - + getPort() + " got unexpected parcel:\n" - + "sample=" + sample + "\n" - + "etalon=" + etalon); - throw new TestFailure( - "parcel context is unexpected to client"); - } - } - - if (istream.available() > 0) { - int datum = istream.read(); - throw new TestFailure( - "client has read ambigous byte: " + datum); - } - ostream.close(); // implies: socket.close() - - } catch (Exception oops) { - exception = oops; - } - } - - /** - * Establish lots of connections to server socket, attack servers with - * huge data parcels, and check if they reply correctly. The number of - * connections to try, the address and port number for the server socket - * are passed through args[], like: - *

-         *    java network006$Client connections_to_try address port
-         * 
- */ - public static void main(String args[]) { - if (DEBUG_MODE) { - try { - String filename = "Client" + ((args.length == 3) ? args[2] : "new"); - displayStream = new PrintStream(filename + ".out"); - complainStream = new PrintStream(filename + ".err"); - } catch (FileNotFoundException exception) { - complain(exception); - } - - } - - if (args.length != 3) { - complain("Client expects 3 paramenets:"); - complain(" java " + Client.class.getName() + " connections_to_try address port"); - exit(1); // FAILED - } - - int CONNECTIONS = Integer.parseInt(args[0]); - display("Client VM: will try " + CONNECTIONS + " connections."); - InetAddress address; - try { - address = InetAddress.getByName(args[1]); - } catch (UnknownHostException exception) { - address = null; - complain("Client: cannot find host: \"" + args[1] + "\""); - exit(4); - } - display("Client: host to contact: " + address); - int port = Integer.parseInt(args[2]); - display("Client: port to contact: " + port); - - // - // Establish connections, and start client processes: - // - - Client client[] = new Client[CONNECTIONS]; - for (int i = 0; i < CONNECTIONS; i++) - try { - client[i] = new Client(address, port); - display("Client #" + i + ": " + client[i]); - - } catch (IOException ioe) { - complain("Client #" + i + "(creation): " + ioe); - ioe.printStackTrace(complainStream); - complainStream.flush(); -// complain("Client #" + i + "(creation): " + ioe.getStackTrace()); - exit(3); - } - - for (int i = 0; i < CONNECTIONS; i++) - client[i].start(); - - // - // Wait until testing is not finished: - // - - int status = 0; - for (int i = 0; i < CONNECTIONS; i++) { - display("Client: waiting for #" + i); - if (client[i].isAlive()) { - display("Client #" + i + ": (joining...)" + client[i]); - - try { - client[i].join(); - } catch (InterruptedException ie) { - complain("Client #" + i + ": " + ie); - status = 3; - } - } - if (client[i].exception != null) { - if (client[i].message != null) - complain("Client #" + i + "(finished) with message: " + client[i].message); - complain("Client #" + i + "(finished): " + client[i].exception); - client[i].exception.printStackTrace(complainStream); - complainStream.flush(); - if (status == 0) - status = 2; - } - } - - exit(status); - } - - /** - * Print error message. - */ - private static synchronized void complain(Object message) { - complainStream.println("# " + message); - complainStream.flush(); - } - - /** - * Display execution trace. - */ - private static synchronized void display(Object message) { - if (!DEBUG_MODE) - return; - displayStream.println(message.toString()); - displayStream.flush(); - } - - /** - * Exit with JCK-like status. - */ - private static void exit(int exitCode) { - int status = exitCode + 95; -// display("Client: exiting with code=" + status); - System.exit(status); - } - } - - /** - * Two of such threads should redirect out and err - * streams of client VM. - */ - private static class IORedirector extends Thread { - /** - * Source stream. - */ - InputStream in; - /** - * Destination stream. - */ - OutputStream out; - - /** - * Redirect in to out. - */ - public IORedirector(InputStream in, OutputStream out) { - this.in = in; - this.out = out; - } - - /** - * Read input stream until the EOF, and write everithing to output stream. - * If output stream is assigned to null, do not print anything, - * but read the input stream anywhere. - */ - public void run() { - try { - for (; ; ) { - int symbol = in.read(); - if (symbol < 0) - break; // EOF - if (out != null) - out.write(symbol); - } - - if (out != null) - out.flush(); - - } catch (Exception exception) { - throw new TestFailure("IORedirector exception: " + exception); - } - } - } - - //----------------------------------------------------------------// - - /** - * A data parcel to be sent/recieved between Client VM and Server thread. - * When data parcel is sent, first 4 bytes are transfered which encode the - * int number equal to size of the parcel minus 1. I.e.: if - * number of data bytes in the parcel's contents is N, then - * the first 4 bytes encode the number N-1. After that, the - * parcel's contents bytes are transered. - */ - static class Parcel { - private byte[] parcel; - - /** - * Display all bytes as integer values from 0 to 255; - * or return ``null'' if this Parcel is not - * yet initialized. - */ - public String toString() { - if (parcel == null) - return "null"; - String s = "{"; - for (int i = 0; i < parcel.length; i++) - s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF); - return s + "}"; - } - - /** - * Generate new parcel[] array using the given - * random numbers generator. Client and Server - * threads should use identical random generators, - * so that those threads could generate equal data parcels and - * check the parcel just transfered. - */ - public Parcel(Random random) { - int size = random.nextInt(MAX_PARCEL) + 1; - parcel = new byte[size]; - for (int i = 0; i < size; i++) - parcel[i] = (byte) random.nextInt(256); - } - - /** - * Read exactly size bytes from the istream - * if possible, or throw TestFailure if unexpected end of - * istream occurs. - */ - private static byte[] readBytes(int size, InputStream istream) - throws IOException { - - byte data[] = new byte[size]; - for (int i = 0; i < size; i++) { - int datum = istream.read(); - if (datum < 0) - throw new TestFailure( - "unexpected EOF: have read: " + i + " bytes of " + size); - data[i] = (byte) datum; - } - return data; - } - - /** - * Read 4 bytes from istream and threat them to encode - * size of data parcel following these 4 bytes. - */ - private static int getSize(InputStream istream) throws IOException { - byte data[] = readBytes(4, istream); - int data0 = (int) data[0] & 0xFF; - int data1 = (int) data[1] & 0xFF; - int data2 = (int) data[2] & 0xFF; - int data3 = (int) data[3] & 0xFF; - int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24); - int size = sizeWord + 1; - if (size <= 0) - throw new TestFailure("illegal size: " + size); - return size; - } - - /** - * Send 4 bytes encoding actual size of the parcel just to be transfered. - */ - private static void putSize(OutputStream ostream, int size) - throws IOException { - - if (size <= 0) - throw new TestFailure("illegal size: " + size); - - int sizeWord = size - 1; - byte data[] = new byte[4]; - data[0] = (byte) sizeWord; - data[1] = (byte) (sizeWord >> 8); - data[2] = (byte) (sizeWord >> 16); - data[3] = (byte) (sizeWord >> 24); - ostream.write(data); - } - - /** - * Recieve data parcel. - */ - public Parcel(InputStream istream) throws IOException { - int size = getSize(istream); - parcel = readBytes(size, istream); - } - - /** - * Send this data parcel. - */ - public void send(OutputStream ostream) throws IOException { - int size = parcel.length; - putSize(ostream, size); - ostream.write(parcel); - } - - /** - * Check byte-to-byte equality between this and the - * other parcels. - */ - public boolean equals(Parcel other) { - if (this.parcel.length != other.parcel.length) - return false; - int size = parcel.length; - for (int i = 0; i < size; i++) - if (this.parcel[i] != other.parcel[i]) - return false; - return true; - } - } - - /** - * Server or Client may throw this exception to report the test failure. - */ - static class TestFailure extends RuntimeException { - /** - * Report particular purpose of the test failure. - */ - public TestFailure(String purpose) { - super(purpose); - } - } -}