8222829: DatagramSocket.setSoTimeout does not specify IAE when timeout is negative
authorpconcannon
Tue, 08 Oct 2019 15:03:20 +0100
changeset 58502 7cb1218ef4d0
parent 58501 6fc4a729763e
child 58503 726a3945e934
8222829: DatagramSocket.setSoTimeout does not specify IAE when timeout is negative Summary: Clarifies behaviour of setSoTimeout() method when given negative timeout value. Reviewed-by: alanb, chegar, dfuchs
src/java.base/share/classes/java/net/DatagramSocket.java
test/jdk/java/net/DatagramSocket/DatagramTimeout.java
--- a/src/java.base/share/classes/java/net/DatagramSocket.java	Tue Oct 08 14:56:46 2019 +0100
+++ b/src/java.base/share/classes/java/net/DatagramSocket.java	Tue Oct 08 15:03:20 2019 +0100
@@ -899,12 +899,15 @@
      *
      * @param timeout the specified timeout in milliseconds.
      * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
+     * @throws IllegalArgumentException if {@code timeout} is negative
      * @since   1.1
      * @see #getSoTimeout()
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException {
         if (isClosed())
             throw new SocketException("Socket is closed");
+        if (timeout < 0)
+            throw new IllegalArgumentException("timeout < 0");
         getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
     }
 
--- a/test/jdk/java/net/DatagramSocket/DatagramTimeout.java	Tue Oct 08 14:56:46 2019 +0100
+++ b/test/jdk/java/net/DatagramSocket/DatagramTimeout.java	Tue Oct 08 15:03:20 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -23,32 +23,56 @@
 
 /**
  * @test
- * @bug 4163126
- * @summary  test to see if timeout hangs
- * @run main/timeout=15 DatagramTimeout
+ * @bug 4163126 8222829
+ * @summary Test to see if timeout hangs. Also checks that
+ * negative timeout value fails as expected.
+ * @run testng DatagramTimeout
  */
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.SocketTimeoutException;
+import java.nio.channels.DatagramChannel;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.expectThrows;
+
 
 public class DatagramTimeout {
-    public static void main(String[] args) throws Exception {
-        boolean success = false;
-        DatagramSocket sock = new DatagramSocket();
+    private static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
+    private static final Class<SocketTimeoutException> STE = SocketTimeoutException.class;
 
-        try {
-            DatagramPacket p;
+    /**
+     * Test DatagramSocket setSoTimeout with a valid timeout value.
+     */
+    @Test
+    public void testSetTimeout() throws Exception {
+        try (DatagramSocket s = new DatagramSocket()) {
             byte[] buffer = new byte[50];
-            p = new DatagramPacket(buffer, buffer.length);
-            sock.setSoTimeout(2);
-            sock.receive(p);
-        } catch (SocketTimeoutException e) {
-            success = true;
-        } finally {
-            sock.close();
+            DatagramPacket p = new DatagramPacket(buffer, buffer.length);
+            s.setSoTimeout(2);
+            expectThrows(STE, () -> s.receive(p));
         }
-        if (!success)
-            throw new RuntimeException("Socket timeout failure.");
     }
 
+    /**
+     * Test DatagramSocket setSoTimeout with a negative timeout.
+     */
+    @Test
+    public void testSetNegativeTimeout() throws Exception {
+        try (DatagramSocket s = new DatagramSocket()) {
+            expectThrows(IAE, () -> s.setSoTimeout(-1));
+        }
+    }
+
+    /**
+     * Test DatagramSocketAdaptor setSoTimeout with a negative timeout.
+     */
+    @Test
+    public void testNegativeTimeout() throws Exception {
+        try (DatagramChannel dc = DatagramChannel.open()) {
+            var s = dc.socket();
+            expectThrows(IAE, () -> s.setSoTimeout(-1));
+        }
+    }
 }