1 /*
   2  * Copyright (c) 2014, 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 /*
  25  * @test
  26  * @bug 8032808 8044773
  27  * @modules jdk.net
  28  * @library /lib/testlibrary
  29  * @build jdk.testlibrary.*
  30  * @run main/othervm -Xcheck:jni Test success
  31  * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail
  32  * @run main/othervm/policy=policy.success -Xcheck:jni Test success
  33  */
  34 
  35 import jdk.net.ExtendedSocketOptions;
  36 import jdk.net.SocketFlow;
  37 import jdk.net.Sockets;
  38 import jdk.testlibrary.OSInfo;
  39 
  40 import java.io.IOException;
  41 import java.net.*;
  42 import java.nio.channels.AsynchronousSocketChannel;
  43 import java.nio.channels.DatagramChannel;
  44 import java.nio.channels.SocketChannel;
  45 import java.util.concurrent.Future;
  46 
  47 import static java.lang.System.out;
  48 import static jdk.net.ExtendedSocketOptions.SO_FLOW_SLA;
  49 
  50 public class Test {
  51 
  52     interface Runner { void run() throws Exception; }
  53 
  54     static boolean expectSuccess;
  55     private static final boolean expectSupport = checkExpectedOptionSupport();
  56     private static final double solarisVersionToCheck = 11.2;
  57 
  58     public static void main(String[] args) throws Exception {
  59 
  60         // quick check to see if supportedOptions() working before
  61         // creating any sockets and libnet loaded
  62 
  63         Sockets.supportedOptions(Socket.class);
  64 
  65         expectSuccess = args[0].equals("success");
  66 
  67         // Main thing is to check for JNI problems
  68         // Doesn't matter if currently setting the option with the loopback
  69         // interface doesn't work
  70 
  71         boolean sm = System.getSecurityManager() != null;
  72         out.println("Security Manager enabled: " + sm);
  73         out.println("Success expected: " + expectSuccess);
  74 
  75         SocketFlow flowIn = SocketFlow.create()
  76                                       .bandwidth(1000)
  77                                       .priority(SocketFlow.HIGH_PRIORITY);
  78 
  79         try (ServerSocket ss = new ServerSocket(0);
  80              DatagramSocket dg = new DatagramSocket(0)) {
  81 
  82             int tcp_port = ss.getLocalPort();
  83             final InetAddress loop = InetAddress.getByName("127.0.0.1");
  84             final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port);
  85 
  86             final int udp_port = dg.getLocalPort();
  87 
  88             final Socket s = new Socket("127.0.0.1", tcp_port);
  89             final SocketChannel sc = SocketChannel.open();
  90             sc.connect(new InetSocketAddress("127.0.0.1", tcp_port));
  91 
  92             doTest("Sockets.setOption Socket", () -> {
  93                 out.println(flowIn);
  94                 if (s.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
  95                     throw new RuntimeException("Unexpected supportedOptions()");
  96                 }
  97                 Sockets.setOption(s, SO_FLOW_SLA, flowIn);
  98                 out.println(flowIn);
  99             });
 100 
 101             doTest("Sockets.getOption Socket", () -> {
 102                 Sockets.getOption(s, SO_FLOW_SLA);
 103                 out.println(flowIn);
 104             });
 105 
 106             doTest("Sockets.setOption SocketChannel", () -> {
 107                 if (sc.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
 108                     throw new RuntimeException("Unexpected supportedOptions()");
 109                 }
 110                 sc.setOption(SO_FLOW_SLA, flowIn);
 111             });
 112             doTest("Sockets.getOption SocketChannel", () ->
 113                     sc.getOption(SO_FLOW_SLA)
 114             );
 115             doTest("Sockets.setOption DatagramSocket", () -> {
 116                 try (DatagramSocket dg1 = new DatagramSocket(0)) {
 117                     if (dg1.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
 118                         throw new RuntimeException("Unexpected supportedOptions()");
 119                     }
 120 
 121                     dg1.connect(loop, udp_port);
 122                     Sockets.setOption(dg1, SO_FLOW_SLA, flowIn);
 123                 }
 124             });
 125             doTest("Sockets.setOption DatagramSocket 2", () -> {
 126                 try (DatagramChannel dg2 = DatagramChannel.open()) {
 127                     if (dg2.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
 128                         throw new RuntimeException("Unexpected supportedOptions()");
 129                     }
 130                     dg2.bind(new InetSocketAddress(loop, 0));
 131                     dg2.connect(new InetSocketAddress(loop, udp_port));
 132                     dg2.setOption(SO_FLOW_SLA, flowIn);
 133                 }
 134             });
 135             doTest("Sockets.setOption MulticastSocket", () -> {
 136                 try (MulticastSocket mc1 = new MulticastSocket(0)) {
 137                     if (mc1.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
 138                         throw new RuntimeException("Unexpected supportedOptions()");
 139                     }
 140                     mc1.connect(loop, udp_port);
 141                     Sockets.setOption(mc1, SO_FLOW_SLA, flowIn);
 142                 }
 143             });
 144             doTest("Sockets.setOption AsynchronousSocketChannel", () -> {
 145                 try (AsynchronousSocketChannel asc = AsynchronousSocketChannel.open()) {
 146                     if (asc.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
 147                         throw new RuntimeException("Unexpected supportedOptions()");
 148                     }
 149                     Future<Void> f = asc.connect(loopad);
 150                     f.get();
 151                     asc.setOption(SO_FLOW_SLA, flowIn);
 152                 }
 153             });
 154         }
 155     }
 156 
 157     static void doTest(String message, Runner func) throws Exception {
 158         out.println(message);
 159         try {
 160             func.run();
 161             if (expectSuccess) {
 162                 out.println("Completed as expected");
 163             } else {
 164                 throw new RuntimeException("Operation succeeded, but expected SecurityException");
 165             }
 166         } catch (SecurityException e) {
 167             if (expectSuccess) {
 168                 throw new RuntimeException("Unexpected SecurityException", e);
 169             } else {
 170                 out.println("Caught expected: " + e);
 171                 return;
 172             }
 173         } catch (UnsupportedOperationException e) {
 174             if (expectSupport) {
 175                 throw new RuntimeException("Test failed: " +
 176                         "unexpected UnsupportedOperationException");
 177             }
 178             out.println("UnsupportedOperationException as expected");
 179             return;
 180         } catch (IOException e) {
 181             // Probably a permission error, but we're not
 182             // going to check unless a specific permission exception
 183             // is defined.
 184             System.out.println(e);
 185         }
 186         if (!expectSupport) {
 187             throw new RuntimeException("Test failed: " +
 188                     "UnsupportedOperationException was not thrown");
 189         }
 190     }
 191 
 192     private static boolean checkExpectedOptionSupport() {
 193         if (OSInfo.getOSType().equals(OSInfo.OSType.SOLARIS)) {
 194             double solarisVersion = OSInfo.getSolarisVersion();
 195             if (solarisVersion >= solarisVersionToCheck) {
 196                 System.out.println("This Solaris version (" + solarisVersion
 197                         + ") should support SO_FLOW_SLA option");
 198                 return true;
 199             } else {
 200                 System.out.println("This Solaris version (" + solarisVersion
 201                         + ") should not support SO_FLOW_SLA option");
 202             }
 203         } else {
 204             System.out.println("Not Solaris, SO_FLOW_SLA should not be " +
 205                     "supported");
 206         }
 207         return false;
 208     }
 209 
 210 }