changeset 59405:569fa0444844

8245569: Add jtreg tests for SO_INCOMING_NAPI_ID Reviewed-by: dfuchs, pconcannon Contributed-by: vladimir.a.ivanov@intel.com
author sviswanathan
date Fri, 22 May 2020 10:18:34 -0700
parents f63f09d7d39e
children 6d7c3a8bfab6
files test/jdk/jdk/net/ExtendedSocketOption/AsynchronousSocketChannelNAPITest.java test/jdk/jdk/net/ExtendedSocketOption/DatagramChannelNAPITest.java test/jdk/jdk/net/ExtendedSocketOption/DatagramSocketNAPITest.java test/jdk/jdk/net/ExtendedSocketOption/SocketChannelNAPITest.java test/jdk/jdk/net/ExtendedSocketOption/SocketNAPITest.java
diffstat 5 files changed, 631 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/ExtendedSocketOption/AsynchronousSocketChannelNAPITest.java	Fri May 22 10:18:34 2020 -0700
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2020, 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 8243099
+ * @library /test/lib
+ * @modules jdk.net
+ * @summary Check ExtendedSocketOption NAPI_ID support for AsynchronousSocketChannel and
+ *          AsynchronousServerSocketChannel
+ * @run testng AsynchronousSocketChannelNAPITest
+ * @run testng/othervm -Djava.net.preferIPv4Stack=true AsynchronousSocketChannelNAPITest
+ */
+
+import jdk.test.lib.net.IPSupport;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousServerSocketChannel;
+import java.nio.channels.AsynchronousSocketChannel;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.assertTrue;
+
+import static jdk.net.ExtendedSocketOptions.SO_INCOMING_NAPI_ID;
+
+public class AsynchronousSocketChannelNAPITest {
+    private InetAddress hostAddr;
+    private static final Class<SocketException> SE = SocketException.class;
+    private static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
+    private static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
+
+    @BeforeTest
+    public void setup() throws IOException {
+        IPSupport.throwSkippedExceptionIfNonOperational();
+        try (var sc = AsynchronousSocketChannel.open();
+             var ssc = AsynchronousServerSocketChannel.open()) {
+            if (!sc.supportedOptions().contains(SO_INCOMING_NAPI_ID)) {
+                assertThrows(UOE, () -> sc.getOption(SO_INCOMING_NAPI_ID));
+                assertThrows(UOE, () -> sc.setOption(SO_INCOMING_NAPI_ID, 42));
+                assertThrows(UOE, () -> sc.setOption(SO_INCOMING_NAPI_ID, null));
+                assertThrows(UOE, () -> ssc.getOption(SO_INCOMING_NAPI_ID));
+                assertThrows(UOE, () -> ssc.setOption(SO_INCOMING_NAPI_ID, 42));
+                assertThrows(UOE, () -> ssc.setOption(SO_INCOMING_NAPI_ID, null));
+                throw new SkipException("NAPI ID not supported on this system");
+            }
+        }
+        hostAddr = InetAddress.getLocalHost();
+    }
+
+    @Test
+    public void testSetGetOptionSocketChannel() throws IOException {
+        try (var sc = AsynchronousSocketChannel.open()) {
+            assertEquals((int) sc.getOption(SO_INCOMING_NAPI_ID), 0);
+            assertThrows(SE, () -> sc.setOption(SO_INCOMING_NAPI_ID, 42));
+            assertThrows(IAE, () -> sc.setOption(SO_INCOMING_NAPI_ID, null));
+        }
+    }
+
+    @Test
+    public void testSetGetOptionServerSocketChannel() throws IOException {
+        try (var ssc = AsynchronousServerSocketChannel.open()) {
+            assertEquals((int) ssc.getOption(SO_INCOMING_NAPI_ID), 0);
+            assertThrows(SE, () -> ssc.setOption(SO_INCOMING_NAPI_ID, 42));
+            assertThrows(IAE, () -> ssc.setOption(SO_INCOMING_NAPI_ID, null));
+        }
+    }
+
+    @Test
+    public void testSocketChannel() throws Exception {
+        int socketID, clientID, tempID = 0;
+        boolean initialRun = true;
+        try (var ss = AsynchronousServerSocketChannel.open()) {
+            ss.bind(new InetSocketAddress(hostAddr, 0));
+
+            try (var c = AsynchronousSocketChannel.open()) {
+                c.connect(ss.getLocalAddress());
+
+                    try(var s = ss.accept().get()) {
+                    assertEquals((int) s.getOption(SO_INCOMING_NAPI_ID), 0);
+
+                    for (int i = 0; i < 10; i++) {
+                        s.write(ByteBuffer.wrap("test".getBytes()));
+                        socketID = s.getOption(SO_INCOMING_NAPI_ID);
+                        assertEquals(socketID, 0, "AsynchronousSocketChannel: Sender");
+
+                        c.read(ByteBuffer.allocate(128));
+                        clientID = ss.getOption(SO_INCOMING_NAPI_ID);
+
+                        // check ID remains consistent
+                        if (initialRun) {
+                            assertTrue(clientID >= 0, "AsynchronousSocketChannel: Receiver");
+                        } else {
+                            assertEquals(clientID, tempID);
+                            initialRun = false;
+                        }
+                        tempID = clientID;
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/ExtendedSocketOption/DatagramChannelNAPITest.java	Fri May 22 10:18:34 2020 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2020, 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 8243099
+ * @library /test/lib
+ * @modules jdk.net
+ * @summary Check ExtendedSocketOption NAPI_ID support for DatagramChannel
+ * @run testng DatagramChannelNAPITest
+ * @run testng/othervm -Djava.net.preferIPv4Stack=true DatagramChannelNAPITest
+ */
+
+import jdk.test.lib.net.IPSupport;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.DatagramChannel;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.assertTrue;
+import static jdk.net.ExtendedSocketOptions.SO_INCOMING_NAPI_ID;
+
+public class DatagramChannelNAPITest {
+    private InetAddress hostAddr;
+    private static final Class<SocketException> SE = SocketException.class;
+    private static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
+    private static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
+
+    @BeforeTest
+    public void setup() throws IOException {
+        IPSupport.throwSkippedExceptionIfNonOperational();
+        try (var dc = DatagramChannel.open()) {
+            if (!dc.supportedOptions().contains(SO_INCOMING_NAPI_ID)) {
+                assertThrows(UOE, () -> dc.getOption(SO_INCOMING_NAPI_ID));
+                assertThrows(UOE, () -> dc.setOption(SO_INCOMING_NAPI_ID, 42));
+                assertThrows(UOE, () -> dc.setOption(SO_INCOMING_NAPI_ID, null));
+                throw new SkipException("NAPI ID not supported on this system");
+            }
+        }
+        hostAddr = InetAddress.getLocalHost();
+    }
+
+    @Test
+    public void testSetGetOptionDatagramChannel() throws IOException {
+        try (var dc = DatagramChannel.open()) {
+            assertEquals((int) dc.getOption(SO_INCOMING_NAPI_ID), 0);
+            assertThrows(SE, () -> dc.setOption(SO_INCOMING_NAPI_ID, 42));
+            assertThrows(IAE, () -> dc.setOption(SO_INCOMING_NAPI_ID, null));
+        }
+    }
+
+    @Test
+    public void testDatagramChannel() throws Exception {
+        int senderID, receiverID, tempID = 0;
+        boolean initialRun = true;
+        try (var r = DatagramChannel.open()) {
+            r.bind(new InetSocketAddress(hostAddr, 0));
+            var port = r.socket().getLocalPort();
+            var addr = new InetSocketAddress(hostAddr, port);
+
+            try (var s = DatagramChannel.open()) {
+                s.bind(null);
+                for (int i = 0; i < 10; i++) {
+                    s.send(ByteBuffer.wrap("test".getBytes()), addr);
+                    senderID = s.getOption(SO_INCOMING_NAPI_ID);
+                    assertEquals(senderID, 0, "DatagramChannel: Sender");
+
+                    r.receive(ByteBuffer.allocate(128));
+                    receiverID = r.getOption(SO_INCOMING_NAPI_ID);
+
+                    // check ID remains consistent
+                    if (initialRun) {
+                        assertTrue(receiverID >= 0, "DatagramChannel: Receiver");
+                    } else {
+                        assertEquals(receiverID, tempID);
+                        initialRun = false;
+                    }
+                    tempID = receiverID;
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/ExtendedSocketOption/DatagramSocketNAPITest.java	Fri May 22 10:18:34 2020 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2020, 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 8243099
+ * @library /test/lib
+ * @modules jdk.net
+ * @summary Check ExtendedSocketOption NAPI_ID support for DatagramSocket
+ * @run testng DatagramSocketNAPITest
+ * @run testng/othervm -Djava.net.preferIPv4Stack=true DatagramSocketNAPITest
+ */
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketException;
+
+import jdk.test.lib.net.IPSupport;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertThrows;
+import static jdk.net.ExtendedSocketOptions.SO_INCOMING_NAPI_ID;
+
+public class DatagramSocketNAPITest {
+    private InetAddress hostAddr;
+    private static final Class<SocketException> SE = SocketException.class;
+    private static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
+    private static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
+
+    @BeforeTest
+    public void setup() throws IOException {
+        IPSupport.throwSkippedExceptionIfNonOperational();
+        try (var ds = new DatagramSocket()) {
+            if (!ds.supportedOptions().contains(SO_INCOMING_NAPI_ID)) {
+                assertThrows(UOE, () -> ds.getOption(SO_INCOMING_NAPI_ID));
+                assertThrows(UOE, () -> ds.setOption(SO_INCOMING_NAPI_ID, 42));
+                assertThrows(UOE, () -> ds.setOption(SO_INCOMING_NAPI_ID, null));
+                throw new SkipException("NAPI ID not supported on this system");
+            }
+        }
+        hostAddr = InetAddress.getLocalHost();
+    }
+
+    @Test
+    public void testSetGetOptionDatagramSocket() throws IOException {
+        try (var ds = new DatagramSocket()) {
+            assertEquals((int) ds.getOption(SO_INCOMING_NAPI_ID), 0);
+            assertThrows(SE, () -> ds.setOption(SO_INCOMING_NAPI_ID, 42));
+            assertThrows(IAE, () -> ds.setOption(SO_INCOMING_NAPI_ID, null));
+        }
+    }
+
+    @Test
+    public void testDatagramSocket() throws Exception {
+        int senderID, receiverID, tempID = 0;
+        boolean initialRun = true;
+        try (var r = new DatagramSocket(new InetSocketAddress(hostAddr, 0))) {
+            var port = r.getLocalPort();
+            var addr = new InetSocketAddress(hostAddr, port);
+
+            try (var s = new DatagramSocket()) {
+                var sendPkt = new DatagramPacket(new byte[128], 128, addr);
+                for (int i = 0; i < 10; i++) {
+                    s.send(sendPkt);
+                    senderID = s.getOption(SO_INCOMING_NAPI_ID);
+                    assertEquals(senderID, 0, "DatagramSocket: Sender");
+
+                    var receivePkt = new DatagramPacket(new byte[128], 128);
+                    r.receive(receivePkt);
+                    receiverID = r.getOption(SO_INCOMING_NAPI_ID);
+
+                    // check ID remains consistent
+                    if (initialRun) {
+                        assertTrue(receiverID >= 0, "DatagramSocket: Receiver");
+                    } else {
+                        assertEquals(receiverID, tempID);
+                        initialRun = false;
+                    }
+                    tempID = receiverID;
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/ExtendedSocketOption/SocketChannelNAPITest.java	Fri May 22 10:18:34 2020 -0700
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2020, 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 8243099
+ * @library /test/lib
+ * @modules jdk.net
+ * @summary Check ExtendedSocketOption NAPI_ID support for SocketChannel and
+ *          ServerSocketChannel
+ * @run testng SocketChannelNAPITest
+ * @run testng/othervm -Djava.net.preferIPv4Stack=true SocketChannelNAPITest
+ */
+
+import jdk.test.lib.net.IPSupport;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.assertTrue;
+
+import static jdk.net.ExtendedSocketOptions.SO_INCOMING_NAPI_ID;
+
+public class SocketChannelNAPITest {
+    private InetAddress hostAddr;
+    private static final Class<SocketException> SE = SocketException.class;
+    private static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
+    private static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
+
+    @BeforeTest
+    public void setup() throws IOException {
+        IPSupport.throwSkippedExceptionIfNonOperational();
+        try (var s = SocketChannel.open();
+             var ssc = ServerSocketChannel.open()) {
+            if (!s.supportedOptions().contains(SO_INCOMING_NAPI_ID)) {
+                assertThrows(UOE, () -> s.getOption(SO_INCOMING_NAPI_ID));
+                assertThrows(UOE, () -> s.setOption(SO_INCOMING_NAPI_ID, 42));
+                assertThrows(UOE, () -> s.setOption(SO_INCOMING_NAPI_ID, null));
+                assertThrows(UOE, () -> ssc.getOption(SO_INCOMING_NAPI_ID));
+                assertThrows(UOE, () -> ssc.setOption(SO_INCOMING_NAPI_ID, 42));
+                assertThrows(UOE, () -> ssc.setOption(SO_INCOMING_NAPI_ID, null));
+                throw new SkipException("NAPI ID not supported on this system");
+            }
+        }
+        hostAddr = InetAddress.getLocalHost();
+    }
+
+    @Test
+    public void testSetGetOptionSocketChannel() throws IOException {
+        try (var sc = SocketChannel.open()) {
+            assertEquals((int) sc.getOption(SO_INCOMING_NAPI_ID), 0);
+            assertThrows(SE, () -> sc.setOption(SO_INCOMING_NAPI_ID, 42));
+            assertThrows(IAE, () -> sc.setOption(SO_INCOMING_NAPI_ID, null));
+        }
+    }
+
+    @Test
+    public void testSetGetOptionServerSocketChannel() throws IOException {
+        try (var ssc = ServerSocketChannel.open()) {
+            assertEquals((int) ssc.getOption(SO_INCOMING_NAPI_ID), 0);
+            assertThrows(SE, () -> ssc.setOption(SO_INCOMING_NAPI_ID, 42));
+            assertThrows(IAE, () -> ssc.setOption(SO_INCOMING_NAPI_ID, null));
+        }
+    }
+
+    @Test
+    public void testSocketChannel() throws Exception {
+        int sID, cID, tempID = 0;
+        boolean initialRun = true;
+        try (var ss = ServerSocketChannel.open()) {
+            ss.bind(new InetSocketAddress(hostAddr, 0));
+
+            try (var c = SocketChannel.open()) {
+                c.connect(ss.getLocalAddress());
+
+                try (var s = ss.accept()) {
+                    assertEquals((int) ss.getOption(SO_INCOMING_NAPI_ID), 0);
+
+                    for (int i = 0; i < 10; i++) {
+                        s.write(ByteBuffer.wrap("test".getBytes()));
+                        sID = s.getOption(SO_INCOMING_NAPI_ID);
+                        assertEquals(sID, 0, "SocketChannel: Sender");
+
+                        c.read(ByteBuffer.allocate(128));
+                        cID = c.getOption(SO_INCOMING_NAPI_ID);
+
+                        // check ID remains consistent
+                        if (initialRun) {
+                            assertTrue(cID >= 0, "SocketChannel: Receiver");
+                        } else {
+                            assertEquals(cID, tempID);
+                            initialRun = false;
+                        }
+                        tempID = cID;
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/net/ExtendedSocketOption/SocketNAPITest.java	Fri May 22 10:18:34 2020 -0700
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2020, 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 8243099
+ * @library /test/lib
+ * @modules jdk.net
+ * @summary Check ExtendedSocketOption NAPI_ID support for Socket and
+ *          ServerSocket
+ * @run testng SocketNAPITest
+ * @run testng/othervm -Djava.net.preferIPv4Stack=true SocketNAPITest
+ */
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+
+import jdk.test.lib.net.IPSupport;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.assertTrue;
+
+import static jdk.net.ExtendedSocketOptions.SO_INCOMING_NAPI_ID;
+
+public class SocketNAPITest {
+    private InetAddress hostAddr;
+    private static final Class<SocketException> SE = SocketException.class;
+    private static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
+    private static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
+
+    @BeforeTest
+    public void setup() throws IOException {
+        IPSupport.throwSkippedExceptionIfNonOperational();
+        try (var s = new Socket();
+             var ss = new ServerSocket()) {
+            if (!s.supportedOptions().contains(SO_INCOMING_NAPI_ID)) {
+                assertThrows(UOE, () -> s.getOption(SO_INCOMING_NAPI_ID));
+                assertThrows(UOE, () -> s.setOption(SO_INCOMING_NAPI_ID, 42));
+                assertThrows(UOE, () -> s.setOption(SO_INCOMING_NAPI_ID, null));
+                assertThrows(UOE, () -> ss.getOption(SO_INCOMING_NAPI_ID));
+                assertThrows(UOE, () -> ss.setOption(SO_INCOMING_NAPI_ID, 42));
+                assertThrows(UOE, () -> ss.setOption(SO_INCOMING_NAPI_ID, null));
+                throw new SkipException("NAPI ID not supported on this system");
+            }
+        }
+        hostAddr = InetAddress.getLocalHost();
+    }
+
+    @Test
+    public void testSetGetOptionSocket() throws IOException {
+        try (var s = new Socket()) {
+            assertEquals((int) s.getOption(SO_INCOMING_NAPI_ID), 0);
+            assertThrows(SE, () -> s.setOption(SO_INCOMING_NAPI_ID, 42));
+            assertThrows(IAE, () -> s.setOption(SO_INCOMING_NAPI_ID, null));
+        }
+    }
+
+    @Test
+    public void testSetGetOptionServerSocket() throws IOException {
+        try (var ss = new ServerSocket()) {
+            assertEquals((int) ss.getOption(SO_INCOMING_NAPI_ID), 0);
+            assertThrows(SE, () -> ss.setOption(SO_INCOMING_NAPI_ID, 42));
+            assertThrows(IAE, () -> ss.setOption(SO_INCOMING_NAPI_ID, null));
+        }
+    }
+
+    @Test
+    public void testSocket() throws Exception {
+        int cID, sID;
+        int temp_sID = 0, temp_cID = 0;
+        boolean initialRun = false;
+        // server socket
+        try (var ss = new ServerSocket()) {
+            ss.bind(new InetSocketAddress(hostAddr, 0));
+            var port = ss.getLocalPort();
+            var addr = ss.getInetAddress();
+
+            //client socket
+            try (var c = new Socket()) {
+                c.connect(new InetSocketAddress(addr, port));
+                var cisr = new InputStreamReader(c.getInputStream());
+                var cbr = new BufferedReader(cisr);
+                var cps = new PrintStream(c.getOutputStream());
+
+                //accepting socket
+                try (var s = ss.accept()) {
+                    var sisr = new InputStreamReader(s.getInputStream());
+                    var sbr = new BufferedReader(sisr);
+                    var sps = new PrintStream(s.getOutputStream());
+
+                    for (int i = 0; i < 10; i++) {
+                        cps.println("client");
+                        sbr.readLine();
+                        cps.flush();
+
+                        sps.println("server");
+                        cbr.readLine();
+                        sps.flush();
+
+                        // check ID remains consistent
+                        sID = s.getOption(SO_INCOMING_NAPI_ID);
+                        cID = c.getOption(SO_INCOMING_NAPI_ID);
+                        if(initialRun) {
+                            assertTrue(sID >= 0, "Socket: Server");
+                            assertTrue(cID >= 0, "Socket: Client");
+                        } else {
+                            assertEquals(temp_cID, cID);
+                            assertEquals(temp_sID, sID);
+                            initialRun = false;
+                        }
+                        temp_sID = sID;
+                        temp_cID = cID;
+                    }
+                }
+            }
+        }
+    }
+}