Home | History | Annotate | Download | only in output
      1 /*******************************************************************************
      2  * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
      3  * All rights reserved. This program and the accompanying materials
      4  * are made available under the terms of the Eclipse Public License v1.0
      5  * which accompanies this distribution, and is available at
      6  * http://www.eclipse.org/legal/epl-v10.html
      7  *
      8  * Contributors:
      9  *    Marc R. Hoffmann - initial API and implementation
     10  *
     11  *******************************************************************************/
     12 package org.jacoco.agent.rt.internal.output;
     13 
     14 import java.io.IOException;
     15 import java.io.InputStream;
     16 import java.io.InterruptedIOException;
     17 import java.io.OutputStream;
     18 import java.net.InetAddress;
     19 import java.net.Socket;
     20 import java.net.SocketAddress;
     21 import java.net.SocketException;
     22 import java.net.SocketImpl;
     23 import java.nio.channels.SocketChannel;
     24 import java.util.Queue;
     25 import java.util.concurrent.ConcurrentLinkedQueue;
     26 
     27 /**
     28  * Simulates two connected {@link Socket} objects. No physical connection is
     29  * established for this. The behavior includes the (inconsistent) exception
     30  * messages have been derived from Sun JDK 1.5.0_18-b02.
     31  */
     32 public class MockSocketConnection {
     33 
     34 	private final MockSocket socketA;
     35 
     36 	private final MockSocket socketB;
     37 
     38 	public MockSocketConnection() throws SocketException {
     39 		socketA = new MockSocket();
     40 		socketB = new MockSocket();
     41 		socketA.connect(socketB);
     42 	}
     43 
     44 	public MockSocket getSocketA() {
     45 		return socketA;
     46 	}
     47 
     48 	public MockSocket getSocketB() {
     49 		return socketB;
     50 	}
     51 
     52 	class MockSocket extends Socket {
     53 
     54 		private MockSocket other;
     55 
     56 		private boolean closed;
     57 
     58 		private final Queue<Byte> buffer = new ConcurrentLinkedQueue<Byte>();
     59 
     60 		private final OutputStream out = new OutputStream() {
     61 
     62 			@Override
     63 			public void write(int b) throws IOException {
     64 				if (closed) {
     65 					throw new SocketException("Socket closed");
     66 				}
     67 				synchronized (other.buffer) {
     68 					other.buffer.add(Byte.valueOf((byte) b));
     69 					other.buffer.notifyAll();
     70 				}
     71 			}
     72 		};
     73 
     74 		private final InputStream in = new InputStream() {
     75 
     76 			@Override
     77 			public int read() throws IOException {
     78 				synchronized (buffer) {
     79 					try {
     80 						while (true) {
     81 							if (closed) {
     82 								throw new SocketException("socket closed");
     83 							}
     84 							if (other.closed) {
     85 								return -1;
     86 							}
     87 							final Byte b = buffer.poll();
     88 							buffer.notifyAll();
     89 							if (b != null) {
     90 								return 0xff & b.intValue();
     91 							}
     92 							buffer.wait();
     93 						}
     94 					} catch (InterruptedException e) {
     95 						throw new InterruptedIOException();
     96 					}
     97 				}
     98 			}
     99 
    100 			@Override
    101 			public int available() throws IOException {
    102 				synchronized (buffer) {
    103 					return buffer.size();
    104 				}
    105 			}
    106 
    107 		};
    108 
    109 		private MockSocket() throws SocketException {
    110 			super((SocketImpl) null);
    111 			closed = false;
    112 		}
    113 
    114 		private void connect(MockSocket other) {
    115 			this.other = other;
    116 			other.other = this;
    117 		}
    118 
    119 		public void waitUntilInputBufferIsEmpty() throws InterruptedException {
    120 			synchronized (buffer) {
    121 				while (!closed && !buffer.isEmpty()) {
    122 					buffer.wait();
    123 				}
    124 			}
    125 		}
    126 
    127 		// socket methods with mocking behavior:
    128 
    129 		@Override
    130 		public OutputStream getOutputStream() throws IOException {
    131 			if (isClosed()) {
    132 				throw new SocketException("Socket is closed");
    133 			}
    134 			return out;
    135 		}
    136 
    137 		@Override
    138 		public InputStream getInputStream() throws IOException {
    139 			if (isClosed()) {
    140 				throw new SocketException("Socket is closed");
    141 			}
    142 			return in;
    143 		}
    144 
    145 		@Override
    146 		public void close() throws IOException {
    147 			synchronized (buffer) {
    148 				closed = true;
    149 				buffer.notifyAll();
    150 			}
    151 			synchronized (other.buffer) {
    152 				other.buffer.notifyAll();
    153 			}
    154 		}
    155 
    156 		@Override
    157 		public boolean isClosed() {
    158 			synchronized (buffer) {
    159 				return closed;
    160 			}
    161 		}
    162 
    163 		// unsupported socket methods:
    164 
    165 		@Override
    166 		public void bind(SocketAddress bindpoint) throws IOException {
    167 			throw new AssertionError();
    168 		}
    169 
    170 		@Override
    171 		public void connect(SocketAddress endpoint, int timeout)
    172 				throws IOException {
    173 			throw new AssertionError();
    174 		}
    175 
    176 		@Override
    177 		public void connect(SocketAddress endpoint) throws IOException {
    178 			throw new AssertionError();
    179 		}
    180 
    181 		@Override
    182 		public SocketChannel getChannel() {
    183 			throw new AssertionError();
    184 		}
    185 
    186 		@Override
    187 		public InetAddress getInetAddress() {
    188 			throw new AssertionError();
    189 		}
    190 
    191 		@Override
    192 		public boolean getKeepAlive() throws SocketException {
    193 			throw new AssertionError();
    194 		}
    195 
    196 		@Override
    197 		public InetAddress getLocalAddress() {
    198 			throw new AssertionError();
    199 		}
    200 
    201 		@Override
    202 		public int getLocalPort() {
    203 			throw new AssertionError();
    204 		}
    205 
    206 		@Override
    207 		public SocketAddress getLocalSocketAddress() {
    208 			throw new AssertionError();
    209 		}
    210 
    211 		@Override
    212 		public boolean getOOBInline() throws SocketException {
    213 			throw new AssertionError();
    214 		}
    215 
    216 		@Override
    217 		public int getPort() {
    218 			throw new AssertionError();
    219 		}
    220 
    221 		@Override
    222 		public synchronized int getReceiveBufferSize() throws SocketException {
    223 			throw new AssertionError();
    224 		}
    225 
    226 		@Override
    227 		public SocketAddress getRemoteSocketAddress() {
    228 			throw new AssertionError();
    229 		}
    230 
    231 		@Override
    232 		public boolean getReuseAddress() throws SocketException {
    233 			throw new AssertionError();
    234 		}
    235 
    236 		@Override
    237 		public synchronized int getSendBufferSize() throws SocketException {
    238 			throw new AssertionError();
    239 		}
    240 
    241 		@Override
    242 		public int getSoLinger() throws SocketException {
    243 			throw new AssertionError();
    244 		}
    245 
    246 		@Override
    247 		public synchronized int getSoTimeout() throws SocketException {
    248 			throw new AssertionError();
    249 		}
    250 
    251 		@Override
    252 		public boolean getTcpNoDelay() throws SocketException {
    253 			throw new AssertionError();
    254 		}
    255 
    256 		@Override
    257 		public int getTrafficClass() throws SocketException {
    258 			throw new AssertionError();
    259 		}
    260 
    261 		@Override
    262 		public boolean isBound() {
    263 			throw new AssertionError();
    264 		}
    265 
    266 		@Override
    267 		public boolean isConnected() {
    268 			throw new AssertionError();
    269 		}
    270 
    271 		@Override
    272 		public boolean isInputShutdown() {
    273 			throw new AssertionError();
    274 		}
    275 
    276 		@Override
    277 		public boolean isOutputShutdown() {
    278 			throw new AssertionError();
    279 		}
    280 
    281 		@Override
    282 		public void sendUrgentData(int data) throws IOException {
    283 			throw new AssertionError();
    284 		}
    285 
    286 		@Override
    287 		public void setKeepAlive(boolean on) throws SocketException {
    288 			throw new AssertionError();
    289 		}
    290 
    291 		@Override
    292 		public void setOOBInline(boolean on) throws SocketException {
    293 			throw new AssertionError();
    294 		}
    295 
    296 		@Override
    297 		public void setPerformancePreferences(int connectionTime, int latency,
    298 				int bandwidth) {
    299 			throw new AssertionError();
    300 		}
    301 
    302 		@Override
    303 		public synchronized void setReceiveBufferSize(int size)
    304 				throws SocketException {
    305 			throw new AssertionError();
    306 		}
    307 
    308 		@Override
    309 		public void setReuseAddress(boolean on) throws SocketException {
    310 			throw new AssertionError();
    311 		}
    312 
    313 		@Override
    314 		public synchronized void setSendBufferSize(int size)
    315 				throws SocketException {
    316 			throw new AssertionError();
    317 		}
    318 
    319 		@Override
    320 		public void setSoLinger(boolean on, int linger) throws SocketException {
    321 			throw new AssertionError();
    322 		}
    323 
    324 		@Override
    325 		public synchronized void setSoTimeout(int timeout)
    326 				throws SocketException {
    327 			throw new AssertionError();
    328 		}
    329 
    330 		@Override
    331 		public void setTcpNoDelay(boolean on) throws SocketException {
    332 			throw new AssertionError();
    333 		}
    334 
    335 		@Override
    336 		public void setTrafficClass(int tc) throws SocketException {
    337 			throw new AssertionError();
    338 		}
    339 
    340 		@Override
    341 		public void shutdownInput() throws IOException {
    342 			throw new AssertionError();
    343 		}
    344 
    345 		@Override
    346 		public void shutdownOutput() throws IOException {
    347 			throw new AssertionError();
    348 		}
    349 
    350 	}
    351 
    352 }
    353