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