1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package libcore.java.nio.channels; 18 19import junit.framework.TestCase; 20 21import java.io.IOException; 22import java.net.Inet4Address; 23import java.net.Inet6Address; 24import java.net.InetAddress; 25import java.net.InetSocketAddress; 26import java.net.NetworkInterface; 27import java.net.StandardProtocolFamily; 28import java.net.StandardSocketOptions; 29import java.net.UnknownHostException; 30import java.nio.ByteBuffer; 31import java.nio.channels.DatagramChannel; 32import java.nio.channels.MembershipKey; 33 34public class MembershipKeyTest extends TestCase { 35 36 private MembershipKey key; 37 private final int PORT = 5000; 38 private final String TEST_MESSAGE = "hello"; 39 private DatagramChannel client; 40 private InetAddress sourceAddress = Inet4Address.LOOPBACK; 41 private final static InetAddress MULTICAST_ADDRESS = getMulticastAddress(); 42 private final static NetworkInterface NETWORK_INTERFACE = getNetworkInterface(); 43 44 private void init(boolean withSource) throws Exception { 45 client = DatagramChannel.open(StandardProtocolFamily.INET) 46 .bind(new InetSocketAddress(Inet4Address.ANY, PORT)); 47 client.configureBlocking(false); 48 49 if (withSource) { 50 key = client.join(MULTICAST_ADDRESS, NETWORK_INTERFACE, sourceAddress); 51 } else { 52 key = client.join(MULTICAST_ADDRESS, NETWORK_INTERFACE); 53 } 54 } 55 56 @Override 57 public void tearDown() throws IOException { 58 client.close(); 59 key = null; 60 } 61 62 public void test_isValid_OnChannelCloseWithJoinWithoutSource() throws Exception { 63 init(false); 64 check_isValid(); 65 } 66 67 public void test_isValid_OnChannelCloseWithJoinWithSource() throws Exception { 68 init(true); 69 check_isValid(); 70 } 71 72 private void check_isValid() throws IOException { 73 assertTrue(key.isValid()); 74 client.close(); 75 assertFalse(key.isValid()); 76 } 77 78 public void test_isValid_OnDropJoinWithoutSource() throws Exception { 79 init(false); 80 check_isValid_OnDrop(); 81 } 82 83 public void test_isValid_OnDropJoinWithSource() throws Exception { 84 init(true); 85 check_isValid_OnDrop(); 86 } 87 88 private void check_isValid_OnDrop() { 89 assertTrue(key.isValid()); 90 key.drop(); 91 assertFalse(key.isValid()); 92 } 93 94 public void test_dropWithJoinWithoutSource() throws Exception { 95 init(false); 96 check_drop(); 97 } 98 99 public void test_dropWithJoinWithSource() throws Exception { 100 init(true); 101 check_drop(); 102 } 103 104 private void check_drop() throws IOException { 105 key.drop(); 106 try(DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) { 107 assertEquals(TEST_MESSAGE.length(), dc 108 .bind(new InetSocketAddress(Inet4Address.LOOPBACK, 0)) 109 .send(ByteBuffer.wrap(TEST_MESSAGE.getBytes()), 110 new InetSocketAddress(MULTICAST_ADDRESS, PORT))); 111 } 112 113 ByteBuffer buffer = ByteBuffer.allocate(1048); 114 client.receive(buffer); 115 buffer.flip(); 116 assertEquals(0, buffer.limit()); 117 } 118 119 public void test_networkInterface() throws Exception { 120 init(false); 121 assertEquals(NETWORK_INTERFACE, key.networkInterface()); 122 client.close(); 123 assertEquals(NETWORK_INTERFACE, key.networkInterface()); 124 } 125 126 public void test_sourceAddressWithJoinWithSource() throws Exception { 127 init(true); 128 assertEquals(sourceAddress, key.sourceAddress()); 129 } 130 131 public void test_sourceAddressWithJoinWithoutSource() throws Exception { 132 init(false); 133 assertNull(key.sourceAddress()); 134 } 135 136 public void test_groupWithJoinWithSource() throws Exception { 137 init(true); 138 assertEquals(MULTICAST_ADDRESS, key.group()); 139 } 140 141 public void test_groupWithoutJoinWIthSource() throws Exception { 142 init(false); 143 assertEquals(MULTICAST_ADDRESS, key.group()); 144 } 145 146 public void test_channelWithJoinWithSource() throws Exception { 147 init(true); 148 assertEquals(client, key.channel()); 149 key.drop(); 150 assertEquals(client, key.channel()); 151 } 152 153 public void test_channelWithJoinWithoutSource() throws Exception { 154 init(false); 155 assertEquals(client, key.channel()); 156 key.drop(); 157 assertEquals(client, key.channel()); 158 } 159 160 public void test_blockWithJoinWithSource() throws Exception { 161 init(true); 162 try { 163 key.block(sourceAddress); 164 fail(); 165 } catch (IllegalStateException expected) {} 166 } 167 168 public void test_blockWithJoinWithoutSource() throws Exception { 169 init(false); 170 key.block(sourceAddress); 171 172 try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) { 173 assertEquals(TEST_MESSAGE.length(), dc 174 .bind(new InetSocketAddress(Inet4Address.LOOPBACK, 0)) 175 .send(ByteBuffer.wrap(TEST_MESSAGE.getBytes()), 176 new InetSocketAddress(MULTICAST_ADDRESS, PORT))); 177 } 178 179 ByteBuffer buffer = ByteBuffer.allocate(1048); 180 client.receive(buffer); 181 buffer.flip(); 182 assertEquals(0, buffer.limit()); 183 } 184 185 public void test_block_Exception () throws Exception { 186 init(false); 187 188 // Blocking a multicast channel 189 try { 190 key.block(Inet4Address.getByName("224.0.0.10")); 191 fail(); 192 } catch (IllegalArgumentException expected) {} 193 194 // Different address type than the group 195 try { 196 key.block(Inet6Address.LOOPBACK); 197 fail(); 198 } catch (IllegalArgumentException expected) {} 199 200 key.drop(); 201 try { 202 key.block(sourceAddress); 203 fail(); 204 } catch (IllegalStateException expected) {} 205 } 206 207 public void test_unblockWithJoinWithSource() throws Exception { 208 init(true); 209 try { 210 key.unblock(Inet4Address.getByName("127.0.0.2")); 211 fail(); 212 } catch (IllegalStateException expected) {} 213 } 214 215 public void test_unblockWithJoinWithoutSource() throws Exception { 216 init(false); 217 218 key.block(sourceAddress); 219 key.unblock(sourceAddress); 220 221 try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) { 222 assertEquals(TEST_MESSAGE.length(), dc 223 .bind(new InetSocketAddress(Inet4Address.LOOPBACK, 0)) 224 .setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true /* enable loop */) 225 .send(ByteBuffer.wrap(TEST_MESSAGE.getBytes()), 226 new InetSocketAddress(MULTICAST_ADDRESS, PORT))); 227 } 228 229 ByteBuffer buffer = ByteBuffer.allocate(1048); 230 client.receive(buffer); 231 buffer.flip(); 232 int limits = buffer.limit(); 233 byte bytes[] = new byte[limits]; 234 buffer.get(bytes, 0, limits); 235 String receivedMessage = new String(bytes); 236 assertEquals(TEST_MESSAGE, receivedMessage); 237 } 238 239 public void test_unblock_Exception() throws Exception { 240 init(false); 241 try { 242 key.unblock(sourceAddress); 243 fail(); 244 } catch (IllegalStateException expected) {} 245 246 key.drop(); 247 248 try { 249 key.unblock(sourceAddress); 250 fail(); 251 } catch (IllegalStateException expected) {} 252 } 253 254 private static InetAddress getMulticastAddress() { 255 try { 256 return InetAddress.getByName("239.255.0.1"); 257 } catch (UnknownHostException exception) { 258 throw new RuntimeException(exception); 259 } 260 } 261 262 private static NetworkInterface getNetworkInterface() { 263 try { 264 return NetworkInterface.getByName("lo"); 265 } catch (Exception e) { 266 throw new RuntimeException(e); 267 } 268 } 269} 270