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
35import jdk.net.ExtendedSocketOptions;
36import jdk.net.SocketFlow;
37import jdk.net.Sockets;
38import jdk.testlibrary.OSInfo;
39
40import java.io.IOException;
41import java.net.*;
42import java.nio.channels.AsynchronousSocketChannel;
43import java.nio.channels.DatagramChannel;
44import java.nio.channels.SocketChannel;
45import java.util.concurrent.Future;
46
47import static java.lang.System.out;
48import static jdk.net.ExtendedSocketOptions.SO_FLOW_SLA;
49
50public 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}
211