1 /*
   2  * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25  * @bug 4640544 8044773
  26  * @summary Unit test for setOption/getOption/options methods
  27  * @run main SocketOptionTests
  28  * @run main/othervm --limit-modules=java.base SocketOptionTests
  29  */
  30 
  31 import java.nio.*;
  32 import java.nio.channels.*;
  33 import java.net.*;
  34 import java.io.IOException;
  35 import java.util.*;
  36 import static java.net.StandardSocketOptions.*;
  37 
  38 public class SocketOptionTests {
  39 
  40     static <T> void checkOption(DatagramChannel dc,
  41                                 SocketOption<T> name,
  42                                 T expectedValue)
  43         throws IOException
  44     {
  45         T value = dc.getOption(name);
  46         if (!value.equals(expectedValue))
  47             throw new RuntimeException("value not as expected");
  48     }
  49 
  50     public static void main(String[] args) throws IOException {
  51         DatagramChannel dc = DatagramChannel.open();
  52 
  53         // check supported options
  54         Set<SocketOption<?>> options = dc.supportedOptions();
  55         boolean reuseport = options.contains(SO_REUSEPORT);
  56         List<? extends SocketOption<?>> expected;
  57         if (reuseport) {
  58            expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF,
  59                       SO_REUSEADDR, SO_REUSEPORT, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF,
  60                       IP_MULTICAST_TTL, IP_MULTICAST_LOOP);
  61         } else {
  62            expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF,
  63                       SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL,
  64                       IP_MULTICAST_LOOP);
  65         }
  66         for (SocketOption opt: expected) {
  67             if (!options.contains(opt))
  68                 throw new RuntimeException(opt.name() + " should be supported");
  69         }
  70 
  71         // check specified defaults
  72         checkOption(dc, SO_BROADCAST, false);
  73         checkOption(dc, IP_MULTICAST_TTL, 1);           // true on supported platforms
  74         checkOption(dc, IP_MULTICAST_LOOP, true);       // true on supported platforms
  75 
  76         // allowed to change when not bound
  77         dc.setOption(SO_BROADCAST, true);
  78         checkOption(dc, SO_BROADCAST, true);
  79         dc.setOption(SO_BROADCAST, false);
  80         checkOption(dc, SO_BROADCAST, false);
  81         dc.setOption(SO_SNDBUF, 128*1024);       // can't check
  82         dc.setOption(SO_RCVBUF, 128*1024);       // can't check
  83         int before, after;
  84         before = dc.getOption(SO_SNDBUF);
  85         after = dc.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF);
  86         if (after < before)
  87             throw new RuntimeException("setOption caused SO_SNDBUF to decrease");
  88         before = dc.getOption(SO_RCVBUF);
  89         after = dc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
  90         if (after < before)
  91             throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
  92         dc.setOption(SO_REUSEADDR, true);
  93         checkOption(dc, SO_REUSEADDR, true);
  94         dc.setOption(SO_REUSEADDR, false);
  95         checkOption(dc, SO_REUSEADDR, false);
  96         if (reuseport) {
  97             dc.setOption(SO_REUSEPORT, true);
  98             checkOption(dc, SO_REUSEPORT, true);
  99             dc.setOption(SO_REUSEPORT, false);
 100             checkOption(dc, SO_REUSEPORT, false);
 101         }
 102         // bind socket
 103         dc.bind(new InetSocketAddress(0));
 104 
 105         // allow to change when bound
 106         dc.setOption(SO_BROADCAST, true);
 107         checkOption(dc, SO_BROADCAST, true);
 108         dc.setOption(SO_BROADCAST, false);
 109         checkOption(dc, SO_BROADCAST, false);
 110         dc.setOption(IP_TOS, 0x08);     // can't check
 111         dc.setOption(IP_MULTICAST_TTL, 2);
 112         checkOption(dc, IP_MULTICAST_TTL, 2);
 113         dc.setOption(IP_MULTICAST_LOOP, false);
 114         checkOption(dc, IP_MULTICAST_LOOP, false);
 115         dc.setOption(IP_MULTICAST_LOOP, true);
 116         checkOption(dc, IP_MULTICAST_LOOP, true);
 117 
 118 
 119         // NullPointerException
 120         try {
 121             dc.setOption(null, "value");
 122             throw new RuntimeException("NullPointerException not thrown");
 123         } catch (NullPointerException x) {
 124         }
 125         try {
 126             dc.getOption(null);
 127             throw new RuntimeException("NullPointerException not thrown");
 128         } catch (NullPointerException x) {
 129         }
 130 
 131         // ClosedChannelException
 132         dc.close();
 133         try {
 134             dc.setOption(IP_MULTICAST_LOOP, true);
 135             throw new RuntimeException("ClosedChannelException not thrown");
 136         } catch (ClosedChannelException x) {
 137         }
 138     }
 139 }