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.dalvik.system; 18 19import android.system.ErrnoException; 20import android.system.StructStat; 21import dalvik.system.SocketTagger; 22import junit.framework.TestCase; 23 24import java.io.FileDescriptor; 25import java.net.DatagramSocket; 26import java.net.Socket; 27import java.net.SocketException; 28import java.nio.channels.DatagramChannel; 29import java.nio.channels.ServerSocketChannel; 30import java.nio.channels.SocketChannel; 31import java.util.Collections; 32import java.util.HashMap; 33import java.util.Map; 34 35public class SocketTaggingTest extends TestCase { 36 static final class StatAndDescriptor { 37 final int fd; 38 final StructStat stat; 39 40 StatAndDescriptor(FileDescriptor fd) { 41 this.fd = fd.getInt$(); 42 this.stat = fstat(fd); 43 } 44 45 @Override 46 public String toString() { 47 return "[fd=" + fd + ", stat=" + stat + "]"; 48 } 49 } 50 51 static class RecordingSocketTagger extends SocketTagger { 52 private final Map<Integer, StatAndDescriptor> liveDescriptors = new HashMap<>(); 53 54 @Override 55 public void tag(FileDescriptor socketDescriptor) throws SocketException { 56 liveDescriptors.put(socketDescriptor.getInt$(), 57 new StatAndDescriptor(socketDescriptor)); 58 } 59 60 @Override 61 public void untag(FileDescriptor socketDescriptor) throws SocketException { 62 StatAndDescriptor existing = liveDescriptors.remove(socketDescriptor.getInt$()); 63 64 // We compare the current description of the descriptor with the description 65 // we used to tag with and make sure they describe the same file. This helps test 66 // whether we untag the socket at the "right" time. 67 StructStat current = fstat(socketDescriptor); 68 assertEquals(existing.stat.st_dev, current.st_dev); 69 assertEquals(existing.stat.st_ino, current.st_ino); 70 } 71 72 public Map<Integer, StatAndDescriptor> getLiveDescriptors() { 73 return liveDescriptors; 74 } 75 } 76 77 private RecordingSocketTagger tagger; 78 private SocketTagger original; 79 80 private ServerSocketChannel server; 81 82 @Override 83 public void setUp() throws Exception { 84 server = ServerSocketChannel.open(); 85 server.configureBlocking(false); 86 server.bind(null); 87 88 original = SocketTagger.get(); 89 tagger = new RecordingSocketTagger(); 90 SocketTagger.set(tagger); 91 } 92 93 @Override 94 public void tearDown() { 95 SocketTagger.set(original); 96 } 97 98 public void testSocketChannel() throws Exception { 99 SocketChannel sc = SocketChannel.open(); 100 sc.connect(server.getLocalAddress()); 101 assertEquals(1, tagger.getLiveDescriptors().size()); 102 103 sc.close(); 104 105 assertEquals(Collections.EMPTY_MAP, tagger.getLiveDescriptors()); 106 } 107 108 public void testServerSocketChannel() throws Exception { 109 ServerSocketChannel ssc = ServerSocketChannel.open(); 110 ssc.bind(null); 111 assertEquals(1, tagger.getLiveDescriptors().size()); 112 113 ssc.close(); 114 115 assertEquals(Collections.EMPTY_MAP, tagger.getLiveDescriptors()); 116 } 117 118 public void testDatagramChannel() throws Exception { 119 DatagramChannel dc = DatagramChannel.open(); 120 dc.connect(server.getLocalAddress()); 121 assertEquals(1, tagger.getLiveDescriptors().size()); 122 123 dc.close(); 124 125 assertEquals(Collections.EMPTY_MAP, tagger.getLiveDescriptors()); 126 } 127 128 public void testSocket() throws Exception { 129 Socket s = new Socket(); 130 s.connect(server.getLocalAddress()); 131 assertEquals(1, tagger.getLiveDescriptors().size()); 132 133 s.close(); 134 135 assertEquals(Collections.EMPTY_MAP, tagger.getLiveDescriptors()); 136 } 137 138 public void testDatagramSocket() throws Exception { 139 DatagramSocket d = new DatagramSocket(); 140 d.connect(server.getLocalAddress()); 141 assertEquals(1, tagger.getLiveDescriptors().size()); 142 143 d.close(); 144 145 assertEquals(Collections.EMPTY_MAP, tagger.getLiveDescriptors()); 146 } 147 148 private static StructStat fstat(FileDescriptor fd) { 149 try { 150 return android.system.Os.fstat(fd); 151 } catch (ErrnoException e) { 152 throw new AssertionError(e); 153 } 154 } 155} 156