/* * Copyright (c) 2019, 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 * @bug 8765432 * @summary Tests async close while receiving packets with zero bytes * @run testng/othervm AsyncCloseReceiveEmpty */ import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.security.Permission; import org.testng.annotations.Test; import static java.lang.String.format; import static java.lang.System.out; import static org.testng.Assert.*; @Test public class AsyncCloseReceiveEmpty { /** Tests asynchronous close when a packet with zero bytes has been received. */ public void testUnconnectedReceive() throws Exception { out.println("\n\n--- testUnconnectedReceive ---"); var dc1 = DatagramChannel.open().bind(null); var dc2 = DatagramChannel.open(); var address = new InetSocketAddress("localhost", dc1.socket().getLocalPort()); out.println(format("Sending empty packet to %s", address)); dc2.send(ByteBuffer.wrap(new byte[0]), address); // SM being used here since it provides a convenient means of injecting // close where we want it SecurityManager sm = new SecurityManager() { @Override public void checkAccept(String host, int port) { out.println(format("Allowing packet from %s:%d. Closing channel", host, port)); try { dc1.close(); out.println("closed"); } catch (IOException e) { fail("UNEXPECTED", e); } } @Override public void checkPermission(Permission perm) { } }; System.setSecurityManager(sm); try { ByteBuffer bb = ByteBuffer.allocate(10); SocketAddress sa = dc1.receive(bb); out.println(format("received from: [%s], data: [%s]", sa, bb)); bb.flip(); assertEquals(bb.remaining(), 0); } finally { System.setSecurityManager(null); } } /** Sanity to ensure packets with zero bytes can be sent and received. */ public void sanity() throws Exception { out.println("\n\n--- sanity ---"); var dc1 = DatagramChannel.open().bind(null); var dc2 = DatagramChannel.open(); var address = new InetSocketAddress("localhost", dc1.socket().getLocalPort()); out.println(format("Sending empty packet to %s", address)); for (int i=0; i<10; i++) dc2.send(ByteBuffer.wrap(new byte[0]), address); ByteBuffer bb = ByteBuffer.allocate(10); for (int i=0; i<10; i++) { bb.clear(); SocketAddress sa = dc1.receive(bb); out.println(format("received from: [%s], data: [%s]", sa, bb)); bb.flip(); assertEquals(bb.remaining(), 0); } } }