package net.sf.expectit;
/*
* #%L
* ExpectIt
* %%
* Copyright (C) 2014 Alexey Gavrilov and contributors
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import static net.sf.expectit.TestUtils.LONG_TIMEOUT;
import static net.sf.expectit.TestUtils.SMALL_TIMEOUT;
import static net.sf.expectit.TestUtils.mockInputStream;
import static net.sf.expectit.echo.EchoAdapters.adapt;
import static net.sf.expectit.matcher.Matchers.contains;
import static net.sf.expectit.matcher.Matchers.times;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.jayway.awaitility.Awaitility;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.nio.channels.ClosedByInterruptException;
import java.nio.charset.Charset;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import net.sf.expectit.echo.EchoOutput;
import net.sf.expectit.filter.Filter;
import net.sf.expectit.matcher.Matcher;
import net.sf.expectit.matcher.Matchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
* Tests for various expect builder parameters
*/
public class ExpectTest {
private Expect expect;
private boolean mockInputReadCalled;
@After
public void cleanup() throws IOException {
if (expect != null) {
expect.close();
expect = null;
}
}
@Test
public void testRequiredParameters() throws IOException {
ExpectBuilder builder = new ExpectBuilder();
expectIllegalState(builder);
builder.withInputs(mock(InputStream.class));
expect = builder.build();
assertEquals(((ExpectImpl) expect).getTimeout(), ExpectBuilder.DEFAULT_TIMEOUT_MS);
try {
expect.sendBytes("".getBytes());
fail();
} catch (NullPointerException ok) {
}
builder.withInputs();
expectIllegalState(builder);
long[] invalidTimeouts = {0, -1, -2, -100};
for (long timeout : invalidTimeouts) {
try {
builder.withTimeout(timeout, TimeUnit.SECONDS);
fail("Should throw IllegalArgumentException for the timeout: " + timeout);
} catch (IllegalArgumentException ok) {
}
}
}
@Test
public void testTimeUnit() throws IOException {
expect = new ExpectBuilder().withInputs(mock(InputStream.class))
.withTimeout(3, TimeUnit.DAYS).build();
assertEquals(((AbstractExpectImpl) expect).getTimeout(), TimeUnit.DAYS.toMillis(3));
assertEquals(((AbstractExpectImpl) expect).getTimeout(), 259200000);
expect.close();
expect = new ExpectBuilder().withInputs(mock(InputStream.class))
.withInfiniteTimeout().build();
assertEquals(((AbstractExpectImpl) expect).getTimeout(), -1);
Expect expect2 = expect.withTimeout(10, TimeUnit.SECONDS);
assertEquals(((AbstractExpectImpl) expect2).getTimeout(), 10000);
assertEquals(((AbstractExpectImpl) expect).getTimeout(), -1);
assertEquals(
((AbstractExpectImpl) expect.withTimeout(
3,
TimeUnit.MILLISECONDS)).getTimeout(), 3);
try {
expect.withTimeout(-10, TimeUnit.DAYS);
Assert.fail();
} catch (IllegalArgumentException ignored) {
}
assertEquals(((AbstractExpectImpl) expect.withInfiniteTimeout()).getTimeout(), -1);
}
private void expectIllegalState(ExpectBuilder builder) throws IOException {
try {
builder.build();
fail();
} catch (IllegalStateException ok) {
}
}
@Test
public void testNumberOfInputs() throws IOException {
ExpectBuilder builder = new ExpectBuilder();
InputStream mock1 = mock(InputStream.class);
InputStream mock2 = mock(InputStream.class);
builder.withInputs(mock1, mock2);
Matcher<?> mock = mock(Matcher.class);
Result result = mock(Result.class);
when(result.isSuccessful()).thenReturn(true);
when(mock.matches(anyString(), eq(false))).thenReturn(result);
expect = builder.build();
assertTrue(expect.expectIn(0, mock).isSuccessful());
assertTrue(expect.expectIn(1, mock).isSuccessful());
try {
expect.expectIn(2, mock);
fail();
} catch (ArrayIndexOutOfBoundsException ok) {
}
}
// remove test when the deprecated method is removed
@Deprecated
@Test
public void testErrorOnTimeout() throws IOException {
ExpectBuilder builder = new ExpectBuilder();
builder.withInputs(mock(InputStream.class));
builder.withOutput(mock(OutputStream.class));
builder.withTimeout(SMALL_TIMEOUT, TimeUnit.MILLISECONDS);
builder.withErrorOnTimeout(true);
expect = builder.build();
Matcher<?> mock = mock(Matcher.class);
Result result = mock(Result.class);
when(result.isSuccessful()).thenReturn(false);
when(mock.matches(anyString(), eq(false))).thenReturn(result);
try {
expect.expect(mock);
fail();
} catch (AssertionError ok) {
}
}
@Test
public void testExceptionOnFailure() throws Exception {
ExpectBuilder builder = new ExpectBuilder();
MockInputStream input = mockInputStream("abc");
builder.withInputs(input.getStream());
builder.withOutput(mock(OutputStream.class));
builder.withTimeout(SMALL_TIMEOUT, TimeUnit.MILLISECONDS);
builder.withExceptionOnFailure();
expect = builder.build();
Matcher<?> mock = mock(Matcher.class);
Result result = mock(Result.class);
when(result.isSuccessful()).thenReturn(false);
when(mock.matches(anyString(), eq(false))).thenReturn(result);
try {
expect.expect(mock);
fail();
} catch (final ExpectIOException ignore) {
assertTrue(ignore.getMessage().contains("fail"));
assertThat(ignore.getInputBuffer(), is("abc"));
}
}
@Test
public void testCharset() throws IOException, InterruptedException {
ExpectBuilder builder = new ExpectBuilder();
InputStream in = mock(InputStream.class);
builder.withInputs(in);
OutputStream out = mock(OutputStream.class);
builder.withOutput(out);
Charset charset = Charset.forName("UTF-16");
builder.withCharset(charset);
expect = builder.build();
String testString = "hello";
final byte[] bytes = testString.getBytes(charset);
expect.send(testString);
verify(out).write(bytes);
configureMockInputStream(in, bytes);
//noinspection deprecation
assertTrue(expect.expect(SMALL_TIMEOUT, contains("hello")).isSuccessful());
}
private void configureMockInputStream(InputStream in, final byte[] bytes)
throws IOException, InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
when(in.read(any(byte[].class))).then(
new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
latch.countDown();
if (mockInputReadCalled) {
return -1;
}
//noinspection SuspiciousSystemArraycopy
System.arraycopy(bytes, 0, invocation.getArguments()[0], 0, bytes.length);
mockInputReadCalled = true;
return bytes.length;
}
});
latch.await();
}
@Test
public void testFilters() throws IOException, InterruptedException {
ExpectBuilder builder = new ExpectBuilder();
InputStream in = mock(InputStream.class);
Appendable echo = mock(Appendable.class);
builder.withInputs(in).withEchoOutput(adapt(echo));
Filter filter1 = mock(Filter.class);
Filter filter2 = mock(Filter.class);
Filter filter3 = mock(Filter.class);
builder.withInputFilters(filter1, filter2, filter3);
when(filter1.beforeAppend(anyString(), any(StringBuilder.class))).thenReturn("xxx");
when(filter2.beforeAppend(eq("xxx"), any(StringBuilder.class))).thenReturn("yyy");
when(filter2.afterAppend(any(StringBuilder.class))).then(
new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
((StringBuilder) invocation.getArguments()[0]).append("01234");
return true;
}
});
expect = builder.build();
String inputStr = "testFilter";
configureMockInputStream(in, inputStr.getBytes());
//noinspection deprecation
assertTrue(expect.expect(SMALL_TIMEOUT, contains("y")).isSuccessful());
verify(filter1).beforeAppend(eq(inputStr), any(StringBuilder.class));
verify(filter2).beforeAppend(eq("xxx"), any(StringBuilder.class));
verify(filter3).beforeAppend(eq("yyy"), any(StringBuilder.class));
verify(filter1).afterAppend(argThat(new StringBuilderArgumentMatcher("yy01234")));
verify(filter2).afterAppend(any(StringBuilder.class));
verify(filter3, never()).afterAppend(any(StringBuilder.class));
// filters are not applied for the echo stream
verify(echo, timeout((int) SMALL_TIMEOUT)).append("testFilter");
}
@SuppressWarnings("deprecation")
@Test
public void testIOException() throws IOException, InterruptedException {
ExpectBuilder builder = new ExpectBuilder();
InputStream in = mock(InputStream.class);
when(in.read(any(byte[].class))).thenThrow(new EOFException(""));
builder.withInputs(in);
expect = builder.build();
try {
expect.expect(LONG_TIMEOUT, contains("test"));
expect.expect(SMALL_TIMEOUT, contains("test"));
fail();
} catch (IOException ok) {
}
}
@Test
public void expectEchoOutput() throws Exception {
ExpectBuilder builder = new ExpectBuilder();
final EchoOutput echoMock = mock(EchoOutput.class);
final EchoOutput echo = new MockedSyncEchoOutput(echoMock);
String inputText = "input";
MockInputStream input = mockInputStream(inputText);
String inputText2 = "number2";
MockInputStream input2 = mockInputStream(inputText2);
builder.withInputs(input.getStream(), input2.getStream());
builder.withEchoOutput(echo);
builder.withOutput(mock(OutputStream.class));
expect = builder.build();
input.waitUntilReady();
input2.waitUntilReady();
String sentText = "sentText";
expect.sendLine(sentText);
String sentTextLine = sentText + "\n";
verify(echoMock).onSend(sentTextLine);
input.push(inputText);
input2.push(inputText2);
input.waitUntilReady();
input2.waitUntilReady();
//noinspection deprecation
assertTrue(expect.expect(LONG_TIMEOUT, times(2, contains(inputText))).isSuccessful());
//noinspection deprecation
assertTrue(expect.expectIn(1, SMALL_TIMEOUT, contains(inputText2)).isSuccessful());
verify(echoMock, Mockito.timeout((int) SMALL_TIMEOUT).times(2)).onReceive(0, inputText);
verify(echoMock, Mockito.timeout((int) SMALL_TIMEOUT).times(2)).onReceive(1, inputText2);
}
@Test
public void expectEchoOutput2() throws Exception {
ExpectBuilder builder = new ExpectBuilder();
Appendable out = mock(Appendable.class);
Appendable in1 = mock(Appendable.class);
Appendable in2 = mock(Appendable.class);
String inputText = "input";
MockInputStream input = mockInputStream(inputText);
String inputText2 = "number2";
MockInputStream input2 = mockInputStream(inputText2);
builder.withInputs(input.getStream(), input2.getStream());
builder.withEchoOutput(out);
builder.withOutput(mock(OutputStream.class));
expect = builder.build();
input.waitUntilReady();
input2.waitUntilReady();
String sentText = "sentText";
expect.sendLine(sentText);
String sentTextLine = sentText + "\n";
verify(out).append(sentTextLine);
builder.withEchoInput(in1);
expect.close();
input = mockInputStream(inputText);
input2 = mockInputStream(inputText2);
builder.withInputs(input.getStream(), input2.getStream());
expect = builder.build();
input.waitUntilReady();
input2.waitUntilReady();
input.push(inputText);
input2.push(inputText2);
//noinspection deprecation
assertTrue(expect.expect(LONG_TIMEOUT, times(2, contains(inputText))).isSuccessful());
//noinspection deprecation
assertTrue(expect.expectIn(1, SMALL_TIMEOUT, contains(inputText2)).isSuccessful());
try {
verify(in1, Mockito.timeout((int) SMALL_TIMEOUT).times(2)).append(inputText);
} catch (AssertionError ignore) {
verify(in1, Mockito.timeout((int) SMALL_TIMEOUT).times(1))
.append(inputText + inputText);
}
reset(in1);
builder.withEchoInput(in1, in2);
expect.close();
input = mockInputStream(inputText);
input2 = mockInputStream(inputText2);
builder.withInputs(input.getStream(), input2.getStream());
expect = builder.build();
input.waitUntilReady();
input2.waitUntilReady();
//noinspection deprecation
assertTrue(expect.expectIn(1, LONG_TIMEOUT, contains(inputText2)).isSuccessful());
verify(in2, Mockito.timeout((int) SMALL_TIMEOUT)).append(inputText2);
verify(in1, Mockito.timeout((int) SMALL_TIMEOUT)).append(inputText);
try {
builder.withEchoInput(in1, in2, in1);
builder.build();
fail();
} catch (IllegalArgumentException ignore) {
}
}
@Test
public void testEchoOutputAutoFlush() throws Exception {
ExpectBuilder builder = new ExpectBuilder();
MockInputStream input1 = mockInputStream("abc");
MockInputStream input2 = mockInputStream("def");
builder.withInputs(input1.getStream(), input2.getStream());
final StringWriter stringWriter1 = new StringWriter();
final StringWriter stringWriter2 = new StringWriter();
final BufferedWriter echo1 = new BufferedWriter(stringWriter1);
final BufferedWriter echo2 = new BufferedWriter(stringWriter2);
builder.withEchoInput(echo1, echo2);
final StringWriter echoOutput = mock(StringWriter.class);
builder.withEchoOutput(echoOutput);
expect = builder.build();
input1.waitUntilReady();
input2.waitUntilReady();
assertTrue(expect.expectIn(0, contains("ab")).isSuccessful());
assertTrue(expect.expectIn(1, contains("def")).isSuccessful());
echo1.flush();
assertThat(stringWriter1.toString(), is("abc"));
assertTrue(stringWriter2.toString().isEmpty());
verify(echoOutput, never()).flush();
expect.close();
verify(echoOutput, never()).flush();
}
@Test
public void testEchoOutputAutoFlush2() throws Exception {
ExpectBuilder builder = new ExpectBuilder();
builder.withAutoFlushEcho(true);
MockInputStream input1 = mockInputStream("abc");
builder.withInputs(input1.getStream());
final StringWriter echoOutput = mock(StringWriter.class);
builder.withEchoOutput(echoOutput);
final StringWriter stringWriter1 = new StringWriter();
final BufferedWriter echo1 = new BufferedWriter(stringWriter1);
builder.withOutput(new ByteArrayOutputStream());
builder.withEchoInput(echo1);
expect = builder.build();
expect.sendLine("xyz");
input1.waitUntilReady();
assertTrue(expect.expect(contains("ab")).isSuccessful());
Awaitility.await()
.atMost(LONG_TIMEOUT, TimeUnit.MILLISECONDS)
.until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return "abc".equals(stringWriter1.toString());
}
});
verify(echoOutput).flush();
reset(echoOutput);
expect.close();
verify(echoOutput, only()).flush();
}
@SuppressWarnings("deprecation")
@Test(timeout = 5000)
public void testExpectMethods() throws Exception {
ExpectBuilder builder = new ExpectBuilder();
String inputText1 = "input1";
String inputText2 = "input2";
MockInputStream input1 = mockInputStream(inputText1);
MockInputStream input2 = mockInputStream(inputText2);
builder.withInputs(input1.getStream(), input2.getStream());
expect = builder.build();
input1.waitUntilReady();
input2.waitUntilReady();
assertFalse(expect.expectIn(1, SMALL_TIMEOUT, contains("input1")).isSuccessful());
assertFalse(expect.expectIn(0, SMALL_TIMEOUT, contains("input2")).isSuccessful());
assertTrue(expect.expect(SMALL_TIMEOUT, contains("input1")).isSuccessful());
assertTrue(expect.expectIn(1, SMALL_TIMEOUT, contains("input2")).isSuccessful());
assertFalse(
expect.expect(SMALL_TIMEOUT, contains("input2"), contains("input1"))
.isSuccessful());
input1.push(inputText1);
assertTrue(
expect.expect(SMALL_TIMEOUT, contains("input"), contains("input"))
.isSuccessful());
}
@Test(timeout = 10000)
public void testClosedByInterruptExceptionIfInterrupted() throws Exception {
MockInputStream input = mockInputStream("input");
expect = new ExpectBuilder().withInputs(input.getStream()).build();
input.waitUntilReady();
final CountDownLatch started = new CountDownLatch(1);
final CountDownLatch exceptionThrown = new CountDownLatch(1);
final AtomicReference<IOException> exceptionRef = new AtomicReference<IOException>();
Thread expectThread = new Thread(
new Runnable() {
@Override
public void run() {
try {
started.countDown();
//noinspection deprecation
assertFalse(
expect.expect(ExpectImpl.INFINITE_TIMEOUT, contains("a"))
.isSuccessful());
fail();
} catch (IOException e) {
exceptionRef.set(e);
exceptionThrown.countDown();
}
}
});
try {
expectThread.start();
assertTrue(started.await(LONG_TIMEOUT, TimeUnit.MILLISECONDS));
// make sure the thread is ready to receive interrupt
Thread.sleep(SMALL_TIMEOUT);
expectThread.interrupt();
expectThread.join();
assertTrue(exceptionThrown.await(LONG_TIMEOUT, TimeUnit.MILLISECONDS));
//noinspection ThrowableResultOfMethodCallIgnored
assertNotNull(exceptionRef.get() instanceof ClosedByInterruptException);
} finally {
expectThread.interrupt();
expectThread.join();
}
}
@Test(timeout = 10000)
public void testExpectWithInfiniteTimeoutWaiting() throws Exception {
MockInputStream input = mockInputStream("input");
expect = new ExpectBuilder().withInputs(input.getStream()).build();
Callable<Void> expectCallable = new Callable<Void>() {
@Override
public Void call() throws IOException {
//noinspection deprecation
assertFalse(
expect.expect(ExpectImpl.INFINITE_TIMEOUT, contains("a"))
.isSuccessful());
fail();
return null;
}
};
input.waitUntilReady();
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> result = executor.submit(expectCallable);
try {
try {
result.get(LONG_TIMEOUT, TimeUnit.MILLISECONDS);
fail();
} catch (TimeoutException ok) {
}
Thread.sleep(SMALL_TIMEOUT * 2);
assertFalse(result.isCancelled());
assertFalse(result.isDone());
} finally {
result.cancel(true);
executor.shutdownNow();
}
}
@Test(timeout = 10000)
public void testExpectWithInfiniteTimeoutConsequentlyPassing() throws Exception {
final String inputString = "input";
final MockInputStream mockInputStream = mockInputStream(inputString);
expect = new ExpectBuilder().withInputs(mockInputStream.getStream()).build();
mockInputStream.waitUntilReady();
final int iterations = 5;
final CountDownLatch successCounter = new CountDownLatch(iterations);
Callable<Void> expectCallable = new Callable<Void>() {
@Override
public Void call() throws Exception {
for (int i = 0; i < iterations; i++) {
mockInputStream.push(inputString);
//noinspection deprecation
assertTrue(
expect.expect(ExpectImpl.INFINITE_TIMEOUT, contains(inputString))
.isSuccessful());
successCounter.countDown();
}
return null;
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> result = executor.submit(expectCallable);
try {
assertTrue(successCounter.await(SMALL_TIMEOUT * iterations, TimeUnit.MILLISECONDS));
assertFalse(result.isCancelled());
} finally {
result.cancel(true);
executor.shutdownNow();
}
}
@Test
public void testCustomLineSeparator() throws IOException {
ExpectBuilder builder = new ExpectBuilder();
builder.withLineSeparator("XYZ");
builder.withInputs(mock(InputStream.class));
OutputStream mock = mock(OutputStream.class);
builder.withOutput(mock);
expect = builder.build();
expect.sendLine("ABZ");
verify(mock).write(("ABZ" + "XYZ").getBytes());
expect.sendLine();
verify(mock).write("XYZ".getBytes());
expect.send("XXx");
verify(mock).write(("XXx").getBytes());
expect.sendBytes("fff".getBytes());
verify(mock).write(("fff").getBytes());
}
@Test
public void testLineSeparator() throws IOException {
ExpectBuilder builder = new ExpectBuilder();
builder.withInputs(mock(InputStream.class));
OutputStream mock = mock(OutputStream.class);
builder.withOutput(mock);
expect = builder.build();
expect.sendLine();
verify(mock).write("\n".getBytes());
}
private static class StringBuilderArgumentMatcher extends ArgumentMatcher<StringBuilder> {
private final String contents;
private StringBuilderArgumentMatcher(String contents) {
this.contents = contents;
}
@Override
public boolean matches(Object argument) {
return argument.toString().equals(contents);
}
}
@Test
public void testBufferSize() throws IOException {
ExpectBuilder builder = new ExpectBuilder();
InputStream mock = mock(InputStream.class);
builder.withInputs(mock);
builder.withOutput(mock(OutputStream.class));
try {
builder.withBufferSize(0);
Assert.fail();
} catch (IllegalArgumentException ignore) {
}
builder.withBufferSize(20);
expect = builder.build();
verify(mock, timeout((int) LONG_TIMEOUT).atLeastOnce())
.read(
argThat(
new ArgumentMatcher<byte[]>() {
@Override
public boolean matches(Object o) {
return o instanceof byte[] && ((byte[]) o).length == 20;
}
}));
}
@Test
public void testCombineInputs() throws Exception {
ExpectBuilder builder = new ExpectBuilder();
String inputText1 = "abc";
String inputText2 = "def";
MockInputStream input1 = mockInputStream(inputText1);
MockInputStream input2 = mockInputStream(inputText2);
builder.withInputs(input1.getStream(), input2.getStream());
builder.withCombineInputs(true);
builder.withTimeout(SMALL_TIMEOUT, TimeUnit.MILLISECONDS);
expect = builder.build();
input1.waitUntilReady();
input2.waitUntilReady();
assertTrue(expect.expect(Matchers.allOf(contains("def"), contains("abc"))).isSuccessful());
assertFalse(expect.expectIn(1, contains("def")).isSuccessful());
}
@Test
public void testExternalExecutor() throws Exception {
ExpectBuilder builder = new ExpectBuilder();
String inputText1 = "abc";
String inputText2 = "def";
MockInputStream input1 = mockInputStream(inputText1);
MockInputStream input2 = mockInputStream(inputText2);
builder.withInputs(input1.getStream(), input2.getStream());
ExecutorService executorService = Executors.newFixedThreadPool(2);
builder.withExecutor(executorService);
builder.withTimeout(SMALL_TIMEOUT, TimeUnit.MILLISECONDS);
expect = builder.build();
input1.waitUntilReady();
input2.waitUntilReady();
assertTrue(expect.expect(contains("abc")).isSuccessful());
assertTrue(expect.expectIn(1, contains("def")).isSuccessful());
expect.close();
assertFalse(executorService.isShutdown());
}
private static class MockedSyncEchoOutput implements EchoOutput {
private final EchoOutput echoMock;
public MockedSyncEchoOutput(final EchoOutput echoMock) {this.echoMock = echoMock;}
@Override
public void onReceive(final int input, final String string) throws
IOException {
synchronized (echoMock) {
echoMock.onReceive(input, string);
}
}
@Override
public void onSend(final String string) throws IOException {
synchronized (echoMock) {
echoMock.onSend(string);
}
}
}
}