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
31import java.nio.*;
32import java.nio.channels.*;
33import java.net.*;
34import java.io.IOException;
35import java.util.*;
36import static java.net.StandardSocketOptions.*;
37
38public 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}
140