1 /*******************************************************************************
2  * Copyright (c) 2009, 2021 Mountainminds GmbH & Co. KG and Contributors
3  * This program and the accompanying materials are made available under
4  * the terms of the Eclipse Public License 2.0 which is available at
5  * http://www.eclipse.org/legal/epl-2.0
6  *
7  * SPDX-License-Identifier: EPL-2.0
8  *
9  * Contributors:
10  *    Marc R. Hoffmann - initial API and implementation
11  *
12  *******************************************************************************/
13 package org.jacoco.agent.rt.internal.output;
14 
15 import static org.junit.Assert.assertEquals;
16 import static org.junit.Assert.assertFalse;
17 import static org.junit.Assert.assertTrue;
18 
19 import java.io.InputStream;
20 import java.io.OutputStream;
21 import java.net.InetAddress;
22 import java.net.ServerSocket;
23 import java.net.Socket;
24 import java.net.SocketException;
25 import java.util.concurrent.Callable;
26 import java.util.concurrent.ExecutionException;
27 import java.util.concurrent.Future;
28 
29 import org.junit.Before;
30 import org.junit.Test;
31 
32 /**
33  * Unit tests for {@link MockSocketConnection}.
34  */
35 public class MockSocketConnectionTest extends ExecutorTestBase {
36 
37 	/**
38 	 * To verify that the tests reflect the behavior of real TCP sockets this
39 	 * flag can be set to <code>true</code>.
40 	 */
41 	private static final boolean REAL_SOCKETS = Boolean
42 			.getBoolean("MockSocketConnectionTest.realSockets");
43 
44 	private Socket a;
45 
46 	private Socket b;
47 
48 	@Before
49 	@Override
setup()50 	public void setup() throws Exception {
51 		super.setup();
52 		if (REAL_SOCKETS) {
53 			createRealSockets();
54 		} else {
55 			createMockSockets();
56 		}
57 	}
58 
createMockSockets()59 	private void createMockSockets() throws Exception {
60 		final MockSocketConnection con = new MockSocketConnection();
61 		a = con.getSocketA();
62 		b = con.getSocketB();
63 	}
64 
createRealSockets()65 	private void createRealSockets() throws Exception {
66 		System.err.println("Using Real Sockets!");
67 		final InetAddress addr = InetAddress.getByName("localhost");
68 		ServerSocket ssocket = new ServerSocket(16300, 1, addr);
69 		a = new Socket(addr, 16300);
70 		b = ssocket.accept();
71 		ssocket.close();
72 	}
73 
74 	@Test
testIsClosed()75 	public void testIsClosed() throws Exception {
76 		assertFalse(a.isClosed());
77 		a.close();
78 		assertTrue(a.isClosed());
79 	}
80 
81 	@Test(expected = SocketException.class)
testGetInputStreamOnClosedSocket()82 	public void testGetInputStreamOnClosedSocket() throws Exception {
83 		a.close();
84 		a.getInputStream();
85 	}
86 
87 	@Test(expected = SocketException.class)
testReadOnClosedSocket()88 	public void testReadOnClosedSocket() throws Exception {
89 		final InputStream in = a.getInputStream();
90 		a.close();
91 		in.read();
92 	}
93 
94 	@Test(expected = SocketException.class)
testReadOnClosedSocketAsync()95 	public void testReadOnClosedSocketAsync() throws Throwable {
96 		final InputStream in = a.getInputStream();
97 		final Future<Void> f = executor.submit(new Callable<Void>() {
98 			public Void call() throws Exception {
99 				in.read();
100 				return null;
101 			}
102 		});
103 
104 		assertBlocks(f);
105 
106 		a.close();
107 		try {
108 			f.get();
109 		} catch (ExecutionException e) {
110 			throw e.getCause();
111 		}
112 	}
113 
114 	@Test(expected = SocketException.class)
testGetOutputStreamOnClosedSocket()115 	public void testGetOutputStreamOnClosedSocket() throws Exception {
116 		a.close();
117 		a.getOutputStream();
118 	}
119 
120 	@Test(expected = SocketException.class)
testWriteOnClosedSocket()121 	public void testWriteOnClosedSocket() throws Exception {
122 		final OutputStream out = a.getOutputStream();
123 		a.close();
124 		out.write(123);
125 	}
126 
127 	@Test
testContents()128 	public void testContents() throws Exception {
129 		final InputStream in = a.getInputStream();
130 		final OutputStream out = b.getOutputStream();
131 
132 		assertEquals(0, in.available());
133 
134 		out.write(0);
135 		out.write(1);
136 		out.write(2);
137 		out.write(255);
138 
139 		if (!REAL_SOCKETS) {
140 			// Real sockets will have a delay
141 			assertEquals(4, in.available());
142 		}
143 
144 		assertEquals(0, in.read());
145 		assertEquals(1, in.read());
146 		assertEquals(2, in.read());
147 		assertEquals(255, in.read());
148 	}
149 
150 	@Test
testWaitForContents()151 	public void testWaitForContents() throws Exception {
152 		final InputStream in = a.getInputStream();
153 		final OutputStream out = b.getOutputStream();
154 
155 		final Future<Byte> f = executor.submit(new Callable<Byte>() {
156 			public Byte call() throws Exception {
157 				return Byte.valueOf((byte) in.read());
158 			}
159 		});
160 
161 		assertBlocks(f);
162 		out.write(123);
163 		assertEquals(123, f.get().byteValue());
164 	}
165 
166 	@Test
testCloseOtherSocket()167 	public void testCloseOtherSocket() throws Exception {
168 		b.close();
169 		final InputStream in = a.getInputStream();
170 		assertEquals(-1, in.read());
171 	}
172 
173 	@Test
testCloseOtherSocketAsync()174 	public void testCloseOtherSocketAsync() throws Exception {
175 		final InputStream in = a.getInputStream();
176 
177 		final Future<Byte> f = executor.submit(new Callable<Byte>() {
178 			public Byte call() throws Exception {
179 				return Byte.valueOf((byte) in.read());
180 			}
181 		});
182 
183 		assertBlocks(f);
184 		b.close();
185 
186 		assertEquals(-1, f.get().byteValue());
187 	}
188 
189 }
190