1/*
2 * Copyright (c) 2007, 2011, 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 4527345
26 * @summary Unit test for DatagramChannel's multicast support
27 * @library /test/lib
28 * @build jdk.test.lib.NetworkConfiguration
29 *        jdk.test.lib.Platform
30 *        BasicMulticastTests
31 * @run main BasicMulticastTests
32 */
33
34import java.nio.ByteBuffer;
35import java.nio.channels.*;
36import java.net.*;
37import java.util.*;
38import java.io.IOException;
39
40import jdk.test.lib.NetworkConfiguration;
41
42public class BasicMulticastTests {
43
44    /**
45     * Tests that existing membership key is returned by join methods and that
46     * membership key methods return the expected results
47     */
48    static void membershipKeyTests(NetworkInterface nif,
49                                   InetAddress group,
50                                   InetAddress source)
51        throws IOException
52    {
53        System.out.format("MembershipKey test using %s @ %s\n",
54            group.getHostAddress(), nif.getName());
55
56        ProtocolFamily family = (group instanceof Inet4Address) ?
57            StandardProtocolFamily.INET : StandardProtocolFamily.INET6;
58
59        DatagramChannel dc = DatagramChannel.open(family)
60            .setOption(StandardSocketOptions.SO_REUSEADDR, true)
61            .bind(new InetSocketAddress(source, 0));
62
63        // check existing key is returned
64        MembershipKey key = dc.join(group, nif);
65        MembershipKey other = dc.join(group, nif);
66        if (other != key) {
67            throw new RuntimeException("existing key not returned");
68        }
69
70        // check key
71        if (!key.isValid())
72            throw new RuntimeException("key is not valid");
73        if (!key.group().equals(group))
74            throw new RuntimeException("group is incorrect");
75        if (!key.networkInterface().equals(nif))
76            throw new RuntimeException("network interface is incorrect");
77        if (key.sourceAddress() != null)
78            throw new RuntimeException("key is source specific");
79
80        // drop membership
81        key.drop();
82        if (key.isValid()) {
83            throw new RuntimeException("key is still valid");
84        }
85
86        // source-specific
87        try {
88            key = dc.join(group, nif, source);
89            other = dc.join(group, nif, source);
90            if (other != key) {
91                throw new RuntimeException("existing key not returned");
92            }
93            if (!key.isValid())
94                throw new RuntimeException("key is not valid");
95            if (!key.group().equals(group))
96                throw new RuntimeException("group is incorrect");
97            if (!key.networkInterface().equals(nif))
98                throw new RuntimeException("network interface is incorrect");
99            if (!key.sourceAddress().equals(source))
100                throw new RuntimeException("key's source address incorrect");
101
102            // drop membership
103            key.drop();
104            if (key.isValid()) {
105                throw new RuntimeException("key is still valid");
106            }
107        } catch (UnsupportedOperationException x) {
108        }
109
110        // done
111        dc.close();
112    }
113
114    /**
115     * Tests exceptions for invalid arguments or scenarios
116     */
117    static void exceptionTests(NetworkInterface nif)
118        throws IOException
119    {
120        System.out.println("Exception Tests");
121
122        DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)
123            .setOption(StandardSocketOptions.SO_REUSEADDR, true)
124            .bind(new InetSocketAddress(0));
125
126        InetAddress group = InetAddress.getByName("225.4.5.6");
127        InetAddress notGroup = InetAddress.getByName("1.2.3.4");
128        InetAddress thisHost = InetAddress.getLocalHost();
129
130        // IllegalStateException
131        MembershipKey key;
132        key = dc.join(group, nif);
133        try {
134            dc.join(group, nif, thisHost);
135            throw new RuntimeException("IllegalStateException not thrown");
136        } catch (IllegalStateException x) {
137        } catch (UnsupportedOperationException x) {
138        }
139        key.drop();
140        try {
141            key = dc.join(group, nif, thisHost);
142            try {
143                dc.join(group, nif);
144                throw new RuntimeException("IllegalStateException not thrown");
145            } catch (IllegalStateException x) {
146            }
147            key.drop();
148        } catch (UnsupportedOperationException x) {
149        }
150
151        // IllegalArgumentException
152        try {
153            dc.join(notGroup, nif);
154            throw new RuntimeException("IllegalArgumentException not thrown");
155        } catch (IllegalArgumentException x) {
156        }
157        try {
158            dc.join(notGroup, nif, thisHost);
159            throw new RuntimeException("IllegalArgumentException not thrown");
160        } catch (IllegalArgumentException x) {
161        } catch (UnsupportedOperationException x) {
162        }
163
164        // NullPointerException
165        try {
166            dc.join(null, nif);
167            throw new RuntimeException("NullPointerException not thrown");
168        } catch (NullPointerException x) {
169        }
170        try {
171            dc.join(group, null);
172            throw new RuntimeException("NullPointerException not thrown");
173        } catch (NullPointerException x) {
174        }
175        try {
176            dc.join(group, nif, null);
177            throw new RuntimeException("NullPointerException not thrown");
178        } catch (NullPointerException x) {
179        } catch (UnsupportedOperationException x) {
180        }
181
182        dc.close();
183
184        // ClosedChannelException
185        try {
186            dc.join(group, nif);
187            throw new RuntimeException("ClosedChannelException not thrown");
188        } catch (ClosedChannelException x) {
189        }
190        try {
191            dc.join(group, nif, thisHost);
192            throw new RuntimeException("ClosedChannelException not thrown");
193        } catch (ClosedChannelException x) {
194        } catch (UnsupportedOperationException x) {
195        }
196    }
197
198
199    /**
200     * Probe interfaces to get interfaces that support IPv4 or IPv6 multicasting
201     * and invoke tests.
202     */
203    public static void main(String[] args) throws IOException {
204
205        // multicast groups used for the test
206        InetAddress ip4Group = InetAddress.getByName("225.4.5.6");
207        InetAddress ip6Group = InetAddress.getByName("ff02::a");
208
209
210        NetworkConfiguration config = NetworkConfiguration.probe();
211
212        NetworkInterface nif = config.ip4MulticastInterfaces().iterator().next();
213        InetAddress anySource = config.ip4Addresses(nif).iterator().next();
214        membershipKeyTests(nif, ip4Group, anySource);
215        exceptionTests(nif);
216
217        // re-run the membership key tests with IPv6 if available
218
219        Iterator<NetworkInterface> iter = config.ip6MulticastInterfaces().iterator();
220        if (iter.hasNext()) {
221            nif = iter.next();
222            anySource = config.ip6Addresses(nif).iterator().next();
223            membershipKeyTests(nif, ip6Group, anySource);
224        }
225    }
226}
227