1 /* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  */
  22 
  23 import java.io.IOException;
  24 import java.net.DatagramSocket;
  25 import java.net.InetAddress;
  26 import java.net.InetSocketAddress;
  27 import java.net.MulticastSocket;
  28 import java.net.SocketException;
  29 
  30 /*
  31  * @test
  32  * @bug 8153674
  33  * @summary Expected SocketException not thrown when calling bind() with 
  34  *   setReuseAddress(false)
  35  * @run main/othervm ReuseAddressTest
  36  */
  37 
  38 public class ReuseAddressTest {
  39 
  40     String getInfo(DatagramSocket soc) {
  41         if (soc == null) {
  42             return null;
  43         }
  44 
  45         return "localPort: " + soc.getLocalPort()
  46                 + "; localAddress: " + soc.getLocalAddress()
  47                 + "; remotePort: " + soc.getPort()
  48                 + "; remoteAddress: " + soc.getInetAddress()
  49                 + "; isClosed: " + soc.isClosed()
  50                 + "; isBound: " + soc.isBound();
  51     }
  52 
  53     static InetSocketAddress createSocketAddress(int testMcastPort) throws Exception {
  54         InetAddress localAddress = InetAddress.getLocalHost();
  55         InetSocketAddress localSocketAddress = new InetSocketAddress(localAddress, testMcastPort);
  56         return localSocketAddress;
  57     }
  58 
  59     /* standalone interface */
  60     public static void main(String argv[]) throws Exception {
  61         ReuseAddressTest test = new ReuseAddressTest();
  62         test.DatagramSocket0029();
  63         test.DatagramSocket0030();
  64         test.DatagramSocket0031();
  65         test.DatagramSocket0032();
  66         test.DatagramSocket0034();
  67         test.DatagramSocket0035();
  68         test.DatagramSocket2028();
  69         test.DatagramSocket2029();
  70         test.DatagramSocket2030();
  71 
  72     }
  73 
  74     /**
  75      * Equivalence class partitioning with input values orientation for public
  76      * void setReuseAddress(boolean on) throws SocketException,
  77      * <br><b>on</b>: false.
  78      * <br><b>Expected results</b>: getReuseAddress() will return false
  79      */
  80     public void DatagramSocket0029() throws Exception {
  81         String testCaseID = "DatagramSocket0029";
  82         System.out.println(" >> " + testCaseID + ": " + "public void setReuseAddress(boolean on) throws SocketException");
  83 
  84         DatagramSocket ds = null;
  85         try {
  86             ds = new DatagramSocket(null);
  87             ds.setReuseAddress(false);
  88             if (ds.getReuseAddress() == true) {
  89                 throw new RuntimeException("SO_REUSEADDR is not set to false");
  90             }
  91         } catch (IOException e) {
  92             e.printStackTrace(System.out);
  93             throw new RuntimeException("unexpected: " + e);
  94         } catch (SecurityException e) {
  95             System.out.println("Security restriction");
  96         } finally {
  97             if (ds != null) {
  98                 ds.close();
  99             }
 100         }
 101 
 102         System.out.println("OKAY");
 103     }
 104 
 105     /**
 106      * Equivalence class partitioning with input values orientation for public
 107      * void setReuseAddress(boolean on) throws SocketException,
 108      * <br><b>on</b>: true.
 109      * <br><b>Expected results</b>: Allows completely duplicate bindings (same
 110      * address and port) on multicast sockets
 111      */
 112     public void DatagramSocket0030() throws Exception {
 113         String testCaseID = "DatagramSocket0030";
 114         System.out.println(" >> " + testCaseID + ": " + "public void setReuseAddress(boolean on) throws SocketException");
 115 
 116         MulticastSocket ms1 = null;
 117         MulticastSocket ms2 = null;
 118         try {
 119             InetSocketAddress addr = createSocketAddress(5050);
 120 
 121             ms1 = new MulticastSocket(null);
 122             ms1.setReuseAddress(true);
 123             if (!ms1.getReuseAddress()) {
 124                 System.out.println("Cannot check: "
 125                         + " safety for SO_REUSEADDR option is not guaranteed");
 126             }
 127 
 128             try {
 129                 ms1.bind(addr);
 130             } catch (SocketException e) {
 131                 throw new RuntimeException("cannot bind first socket to " + addr
 132                         + " unexpected " + e);
 133             }
 134 
 135             ms2 = new MulticastSocket(null);
 136             ms2.setReuseAddress(true);
 137             if (!ms2.getReuseAddress()) {
 138                 System.out.println("Cannot check: "
 139                         + " safety for SO_REUSEADDR option is not guaranteed");
 140             }
 141 
 142             try {
 143                 ms2.bind(addr);
 144             } catch (SocketException e) {
 145                 throw new RuntimeException("cannot bind second socket to " + addr
 146                         + " unexpected " + e);
 147             }
 148 
 149             if (ms1.getLocalPort() != addr.getPort() || !ms1.isBound()
 150                     || ms2.getLocalPort() != addr.getPort() || !ms2.isBound()) {
 151                 System.out.println("bind() fails with: " + addr);
 152                 System.out.println("  ms1 [" + getInfo(ms1) + "]");
 153                 System.out.println("  ms2 [" + getInfo(ms2) + "]");
 154                 System.out.println("  getReuseAddress(): " + ms2.getReuseAddress());
 155                 throw new RuntimeException("bind() fails with: " + addr);
 156             }
 157 
 158         } catch (IOException e) {
 159             e.printStackTrace(System.out);
 160             throw new RuntimeException("unexpected: " + e);
 161         } catch (SecurityException e) {
 162             System.out.println("Security restriction");
 163         } finally {
 164             if (ms1 != null) {
 165                 ms1.close();
 166             }
 167             if (ms2 != null) {
 168                 ms2.close();
 169             }
 170         }
 171 
 172         System.out.println("OKAY");
 173     }
 174 
 175     /**
 176      * Equivalence class partitioning with input values orientation for public
 177      * void setReuseAddress(boolean on) throws SocketException,
 178      * <br><b>on</b>: false.
 179      * <br><b>Expected results</b>: The second bind will throw SocketException,
 180      * when SO_REUSEADDR disable
 181      */
 182     public void DatagramSocket0031() throws Exception {
 183         String testCaseID = "DatagramSocket0031";
 184         System.out.println(" >> " + testCaseID + ": " + "public void setReuseAddress(boolean on) throws SocketException");
 185 
 186         MulticastSocket ms1 = null;
 187         MulticastSocket ms2 = null;
 188         try {
 189             InetSocketAddress addr = createSocketAddress(6060);
 190 
 191             ms1 = new MulticastSocket(null);
 192             try {
 193                 ms1.bind(addr);
 194             } catch (SocketException e) {
 195                 throw new RuntimeException("cannot bind first socket to " + addr
 196                         + " unexpected " + e);
 197             }
 198 
 199             ms2 = new MulticastSocket(null);
 200             ms2.setReuseAddress(false);  // method under test
 201 
 202             try {
 203                 ms2.bind(addr);
 204                 System.out.println("No exceptions: ");
 205                 System.out.println("  addr: " + addr);
 206                 System.out.println("  ms1 [" + getInfo(ms1) + "]");
 207                 System.out.println("  ms2 [" + getInfo(ms2) + "]");
 208                 System.out.println("  getReuseAddress(): " + ms2.getReuseAddress());
 209                 throw new RuntimeException("no exceptions from bind() with " + addr);
 210             } catch (SocketException e) {
 211             }
 212 
 213         } catch (IOException e) {
 214             e.printStackTrace(System.out);
 215             throw new RuntimeException("unexpected: " + e);
 216         } catch (SecurityException e) {
 217             System.out.println("Security restriction");
 218         } finally {
 219             if (ms1 != null) {
 220                 ms1.close();
 221             }
 222             if (ms2 != null) {
 223                 ms2.close();
 224             }
 225         }
 226 
 227         System.out.println("OKAY");
 228     }
 229 
 230     /**
 231      * Equivalence class partitioning with input values orientation for public
 232      * void setReuseAddress(boolean on) throws SocketException,
 233      * <br><b>on</b>: true.
 234      * <br><b>Expected results</b>: Allows a single process to bind the same
 235      * port to multiple sockets as long as each bind specifies a different local
 236      * IP address
 237      */
 238     public void DatagramSocket0032() throws Exception {
 239         String testCaseID = "DatagramSocket0032";
 240         System.out.println(" >> " + testCaseID + ": " + "public void setReuseAddress(boolean on) throws SocketException");
 241 
 242         DatagramSocket ds1 = null;
 243         DatagramSocket ds2 = null;
 244         try {
 245 
 246             InetSocketAddress isa = createSocketAddress(7070);
 247             InetAddress addr = isa.getAddress();
 248             InetAddress wildcard = InetAddress.getByName("0.0.0.0");
 249             if (addr.equals(wildcard) || addr.isLoopbackAddress()) {
 250                 System.out.println("Cannot check: addresses are equal");
 251             }
 252 
 253             InetSocketAddress isa1 = new InetSocketAddress(addr, isa.getPort());
 254             InetSocketAddress isa2 = new InetSocketAddress(wildcard, isa.getPort());
 255 
 256             ds1 = new DatagramSocket(null);
 257             ds1.setReuseAddress(true);    // method under test
 258             if (!ds1.getReuseAddress()) {
 259                 System.out.println("Cannot check: "
 260                         + " safety for SO_REUSEADDR option is not guaranteed");
 261             }
 262             ds1.bind(isa1);
 263 
 264             ds2 = new DatagramSocket(null);
 265             ds2.setReuseAddress(true);    // method under test
 266             if (!ds2.getReuseAddress()) {
 267                 System.out.println("Cannot check: "
 268                         + " safety for SO_REUSEADDR option is not guaranteed");
 269             }
 270 
 271             try {
 272                 ds2.bind(isa2);
 273             } catch (SocketException e) {
 274                 throw new RuntimeException("cannot bind second socket to " + isa2
 275                         + " unexpected " + e);
 276             }
 277 
 278             if (ds1.getLocalPort() != isa.getPort() || !ds1.isBound()
 279                     || ds2.getLocalPort() != isa.getPort() || !ds2.isBound()) {
 280                 System.out.println("bind() fails with: " + addr);
 281                 System.out.println("  ds1 [" + getInfo(ds1) + "]");
 282                 System.out.println("  ds2 [" + getInfo(ds2) + "]");
 283                 System.out.println("  getReuseAddress(): " + ds2.getReuseAddress());
 284                 throw new RuntimeException("bind() fails with: " + addr);
 285             }
 286 
 287         } catch (IOException e) {
 288             e.printStackTrace(System.out);
 289             throw new RuntimeException("unexpected: " + e);
 290         } catch (SecurityException e) {
 291             System.out.println("Security restriction");
 292         } finally {
 293             if (ds1 != null) {
 294                 ds1.close();
 295             }
 296             if (ds2 != null) {
 297                 ds2.close();
 298             }
 299         }
 300 
 301         System.out.println("OKAY");
 302     }
 303 
 304     /**
 305      * Assertion testing for public int getTrafficClass() throws
 306      * SocketException, will return a number in range from 0 to 255 or throw
 307      * SocketException.
 308      */
 309     public void DatagramSocket2028() throws Exception {
 310         String testCaseID = "DatagramSocket2028";
 311         System.out.println(" >> " + testCaseID + ": " + "public int getTrafficClass() throws SocketException");
 312 
 313         DatagramSocket ds = null;
 314         try {
 315             ds = new DatagramSocket();
 316             int tc = ds.getTrafficClass();
 317             if (tc < 0 || tc > 255) {
 318                 throw new RuntimeException("getTrafficClass() returns: " + tc);
 319             }
 320         } catch (SecurityException e) {
 321             System.out.println("Security restriction: " + e);
 322         } catch (SocketException e) {
 323             e.printStackTrace(System.out);
 324             throw new RuntimeException("Unexpected exception : " + e);
 325         } finally {
 326             if (ds != null) {
 327                 ds.close();
 328             }
 329         }
 330 
 331         System.out.println("OKAY");
 332     }
 333 
 334     /**
 335      * Assertion testing for public void setTrafficClass(int tc) throws
 336      * SocketException, IAE will be thrown with tc less than 0 or greater than
 337      * 255.
 338      */
 339     public void DatagramSocket2029() throws Exception {
 340         String testCaseID = "DatagramSocket2029";
 341         System.out.println(" >> " + testCaseID + ": " + "public void setTrafficClass(int tc) throws SocketException");
 342 
 343         DatagramSocket ds = null;
 344         try {
 345             ds = new DatagramSocket();
 346         } catch (SecurityException e) {
 347             System.out.println("Security restriction: " + e);
 348         } catch (IOException e) {
 349             e.printStackTrace(System.out);
 350             throw new RuntimeException("cannot create socket: " + e);
 351         }
 352 
 353         int[] values = {
 354             Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -1000, -2, -1,
 355             256, 257, 1000, 50000, Integer.MAX_VALUE - 1, Integer.MAX_VALUE
 356         };
 357 
 358         for (int i = 0; i < values.length; i++) {
 359             try {
 360                 ds.setTrafficClass(values[i]);
 361                 System.out.println("No exception with: " + values[i]);
 362                 System.out.println("getTrafficClass() returns: " + ds.getTrafficClass());
 363                 ds.close();
 364                 throw new RuntimeException("setTrafficClass() fails with : " + values[i]);
 365             } catch (SocketException e) {
 366                 ds.close();
 367                 e.printStackTrace(System.out);
 368                 throw new RuntimeException("setTrafficClass() throws : " + e);
 369             } catch (IllegalArgumentException e) {
 370             }
 371         }
 372 
 373         System.out.println("OKAY");
 374     }
 375 
 376     /**
 377      * Assertion testing for public void setTrafficClass(int tc) throws
 378      * SocketException, only SocketException may be thrown with tc in range from
 379      * 0 to 255.
 380      */
 381     public void DatagramSocket2030() throws Exception {
 382         String testCaseID = "DatagramSocket2030";
 383         System.out.println(" >> " + testCaseID + ": " + "public void setTrafficClass(int tc) throws SocketException");
 384 
 385         DatagramSocket ds = null;
 386         try {
 387             ds = new DatagramSocket();
 388         } catch (SecurityException e) {
 389             System.out.println("Security restriction: " + e);
 390         } catch (IOException e) {
 391             e.printStackTrace(System.out);
 392             throw new RuntimeException("cannot create socket: " + e);
 393         }
 394 
 395         for (int i = 0; i <= 255; i++) {
 396             try {
 397                 ds.setTrafficClass(i);
 398             } catch (SocketException e) {
 399             }
 400         }
 401 
 402         System.out.println("OKAY");
 403     }
 404 
 405     /**
 406      * Equivalence class partitioning with input values orientation for public
 407      * void setBroadcast(boolean on) throws SocketException,
 408      * <br><b>on</b>: false.
 409      * <br><b>Expected results</b>: getBroadcast() will return false
 410      */
 411     public void DatagramSocket0034() throws Exception {
 412         String testCaseID = "DatagramSocket0034";
 413         System.out.println(" >> " + testCaseID + ": " + "public void setBroadcast(boolean on) throws SocketException");
 414 
 415         DatagramSocket ds = null;
 416         try {
 417             ds = new DatagramSocket();
 418             ds.setBroadcast(false);
 419             if (ds.getBroadcast() == true) {
 420                 throw new RuntimeException("SO_BROADCAST is not set to false");
 421             }
 422         } catch (IOException e) {
 423             e.printStackTrace(System.out);
 424             throw new RuntimeException("unexpected: " + e);
 425         } catch (SecurityException e) {
 426             System.out.println("Security restriction");
 427         } finally {
 428             if (ds != null) {
 429                 ds.close();
 430             }
 431         }
 432 
 433         System.out.println("OKAY");
 434     }
 435 
 436     /**
 437      * Equivalence class partitioning with input values orientation for public
 438      * void setBroadcast(boolean on) throws SocketException,
 439      * <br><b>on</b>: true.
 440      * <br><b>Expected results</b>: getBroadcast() will return true
 441      */
 442     public void DatagramSocket0035() throws Exception {
 443         String testCaseID = "DatagramSocket0035";
 444         System.out.println(" >> " + testCaseID + ": " + "public void setBroadcast(boolean on) throws SocketException");
 445 
 446         DatagramSocket ds = null;
 447         try {
 448             ds = new DatagramSocket();
 449             ds.setBroadcast(true);
 450             if (ds.getBroadcast() == false) {
 451                 throw new RuntimeException("SO_BROADCAST is not set to true");
 452             }
 453         } catch (IOException e) {
 454             e.printStackTrace(System.out);
 455             throw new RuntimeException("unexpected: " + e);
 456         } catch (SecurityException e) {
 457             System.out.println("Security restriction");
 458         } finally {
 459             if (ds != null) {
 460                 ds.close();
 461             }
 462         }
 463 
 464         System.out.println("OKAY");
 465     }
 466 }