diff --git a/test/jdk/java/net/DatagramPacket/ReuseBuf.java b/test/jdk/java/net/DatagramPacket/ReuseBuf.java index 232bd07dded..2213f306a8a 100644 --- a/test/jdk/java/net/DatagramPacket/ReuseBuf.java +++ b/test/jdk/java/net/DatagramPacket/ReuseBuf.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, 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 @@ -21,71 +21,132 @@ * questions. */ -/** + +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketException; +import java.util.concurrent.atomic.AtomicReference; + +/* * @test - * * @bug 4424096 - * - * @summary DatagramPacket spec needs clarification (reuse buf) + * @summary Verify the specification of DatagramPacket.getData() */ -import java.net.*; - public class ReuseBuf { - static String msgs[] = {"Hello World", "Java", "Good Bye"}; - static int port; + private static final String[] msgs = {"Hello World", "Java", "Good Bye"}; - static class ServerThread extends Thread{ - DatagramSocket ds; - public ServerThread() { + static class Server implements Runnable, AutoCloseable { + + private final DatagramSocket ds; + private volatile boolean closed; + private final AtomicReference serverFailure = new AtomicReference<>(); + + public Server(final InetSocketAddress bindAddr) { try { - InetAddress local = InetAddress.getLocalHost(); - InetSocketAddress bindaddr = new InetSocketAddress(local, 0); - ds = new DatagramSocket(bindaddr); - port = ds.getLocalPort(); + this.ds = new DatagramSocket(bindAddr); + } catch (SocketException e) { + throw new RuntimeException(e); + } + System.out.println("Server bound to address: " + this.ds.getLocalSocketAddress()); + } + + private InetSocketAddress getServerAddress() { + return (InetSocketAddress) this.ds.getLocalSocketAddress(); + } + + private static void serverLog(final String msg) { + System.out.println("[server] " + msg); + } + + @Override + public void run() { + serverLog("server processing started"); + try { + doRun(); } catch (Exception e) { - throw new RuntimeException(e.getMessage()); + // no need to be concerned with the exception + // if the server is already closed + if (!closed) { + this.serverFailure.set(e); + System.err.println("server exception: " + e); + e.printStackTrace(); + } + } finally { + close(); } } - public void run() { - byte b[] = new byte[100]; - DatagramPacket dp = new DatagramPacket(b,b.length); - while (true) { - try { - ds.receive(dp); - String reply = new String(dp.getData(), dp.getOffset(), dp.getLength()); - ds.send(new DatagramPacket(reply.getBytes(),reply.length(), - dp.getAddress(),dp.getPort())); - if (reply.equals(msgs[msgs.length-1])) { - break; - } - } catch (Exception e) { - throw new RuntimeException(e.getMessage()); + private void doRun() throws Exception { + byte[] b = new byte[100]; + DatagramPacket dp = new DatagramPacket(b, b.length); + while (!closed) { + serverLog("waiting to receive a message at " + ds.getLocalSocketAddress()); + ds.receive(dp); + String reply = new String(dp.getData(), dp.getOffset(), dp.getLength()); + serverLog("replying to " + dp.getAddress() + ":" + dp.getPort()); + ds.send(new DatagramPacket(reply.getBytes(), reply.length(), + dp.getAddress(), dp.getPort())); + if (reply.equals(msgs[msgs.length - 1])) { + break; } } - ds.close(); + } + + @Override + public void close() { + if (this.closed) { + return; + } + synchronized (this) { + if (this.closed) { + return; + } + this.closed = true; + } + System.out.println("Server closing " + ds.getLocalSocketAddress()); + this.ds.close(); } } - public static void main(String args[]) throws Exception { - ServerThread st = new ServerThread(); - st.start(); - InetAddress local = InetAddress.getLocalHost(); - InetSocketAddress bindaddr = new InetSocketAddress(local, 0); - DatagramSocket ds = new DatagramSocket(bindaddr); - byte b[] = new byte[100]; - DatagramPacket dp = new DatagramPacket(b,b.length); - for (int i = 0; i < msgs.length; i++) { - ds.send(new DatagramPacket(msgs[i].getBytes(),msgs[i].length(), - InetAddress.getLocalHost(), - port)); - ds.receive(dp); - if (!msgs[i].equals(new String(dp.getData(), dp.getOffset(), dp.getLength()))) { - throw new RuntimeException("Msg expected: "+msgs[i] +msgs[i].length()+ - "msg received: "+new String(dp.getData(), dp.getOffset(), dp.getLength())+dp.getLength()); + public static void main(String[] args) throws Exception { + InetSocketAddress loopbackEphemeral = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); + Server server; + Thread serverThread; + try (var _ = server = new Server(loopbackEphemeral); + DatagramSocket ds = new DatagramSocket(loopbackEphemeral)) { + + InetSocketAddress destAddr = server.getServerAddress(); + // start the server + serverThread = new Thread(server); + serverThread.start(); + + byte[] b = new byte[100]; + DatagramPacket dp = new DatagramPacket(b, b.length); + for (String msg : msgs) { + System.out.println("sending message from " + ds.getLocalSocketAddress() + + " to " + destAddr); + ds.send(new DatagramPacket(msg.getBytes(), msg.length(), destAddr)); + // wait for a reply from the server + ds.receive(dp); + System.out.println("received message from: " + dp.getAddress() + ":" + dp.getPort()); + String actual = new String(dp.getData(), dp.getOffset(), dp.getLength()); + if (!msg.equals(actual)) { + throw new RuntimeException("Msg expected: " + msg + + " of length: " + msg.length() + + ", actual received: " + actual + " of length: " + dp.getLength()); + } } + System.out.println("All " + msgs.length + " replies received from the server"); + } + // wait for the server thread to complete + System.out.println("awaiting server thread " + serverThread + " to complete"); + serverThread.join(); + Exception serverFailure = server.serverFailure.get(); + if (serverFailure != null) { + System.err.println("Unexpected failure on server: " + serverFailure); + throw serverFailure; } - ds.close(); - System.out.println("Test Passed!!!"); } }