blob: 239aee37d7c46909b88b79209246f0325d84c243 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2020 Paul Pazderski and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Paul Pazderski - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.tests.console;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import org.eclipse.debug.core.IBinaryStreamListener;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IBinaryStreamMonitor;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.debug.internal.core.OutputStreamMonitor;
import org.eclipse.debug.tests.AbstractDebugTest;
import org.eclipse.debug.tests.TestUtil;
import org.junit.Before;
import org.junit.Test;
/**
* Tests the {@link OutputStreamMonitor}.
*/
public class OutputStreamMonitorTests extends AbstractDebugTest {
/** Stream to simulate an application writing to system out. */
PipedOutputStream sysout = new PipedOutputStream();
/** The {@link OutputStreamMonitor} used for the test runs. */
TestOutputStreamMonitor monitor;
/** The bytes received through listener. */
ByteArrayOutputStream notifiedBytes = new ByteArrayOutputStream();
/** The strings received through listener. */
StringBuilder notifiedChars = new StringBuilder();
IBinaryStreamListener fBinaryListener = new IBinaryStreamListener() {
@Override
public void streamAppended(byte[] data, IBinaryStreamMonitor mon) {
if (monitor == mon) {
try {
notifiedBytes.write(data);
} catch (IOException e) {
}
}
}
};
IStreamListener fStreamListener = new IStreamListener() {
@Override
public void streamAppended(String text, IStreamMonitor mon) {
if (monitor == mon) {
notifiedChars.append(text);
}
}
};
@Override
@Before
@SuppressWarnings("resource")
public void setUp() throws IOException {
monitor = new TestOutputStreamMonitor(new PipedInputStream(sysout), null);
}
/**
* Simple test for output stream monitor. Test buffering and listeners.
*/
@Test
public void testBufferedOutputStreamMonitor() throws Exception {
String input = "o\u00F6O";
byte[] byteInput = input.getBytes(StandardCharsets.UTF_8);
try {
monitor.addBinaryListener(fBinaryListener);
monitor.addListener(fStreamListener);
sysout.write(byteInput, 0, 2);
sysout.flush();
monitor.startMonitoring();
TestUtil.waitWhile(() -> notifiedBytes.size() < 2, 1000);
String contents = monitor.getContents();
assertEquals("Monitor read wrong content.", input.substring(0, 1), contents);
assertEquals("Notified and buffered content differ.", contents, notifiedChars.toString());
assertEquals("Failed to access buffered content twice.", contents, monitor.getContents());
byte[] data = monitor.getData();
byte[] expected = new byte[2];
System.arraycopy(byteInput, 0, expected, 0, 2);
assertArrayEquals("Monitor read wrong binary content.", expected, data);
assertArrayEquals("Notified and buffered binary content differ.", data, notifiedBytes.toByteArray());
assertArrayEquals("Failed to access buffered binary content twice.", data, monitor.getData());
monitor.flushContents();
sysout.write(byteInput, 2, byteInput.length - 2);
sysout.flush();
TestUtil.waitWhile(() -> notifiedBytes.size() < byteInput.length, 1000);
contents = monitor.getContents();
assertEquals("Monitor buffered wrong content.", input.substring(1), contents);
assertEquals("Failed to access buffered content twice.", contents, monitor.getContents());
assertEquals("Wrong content through listener.", input, notifiedChars.toString());
data = monitor.getData();
expected = new byte[byteInput.length - 2];
System.arraycopy(byteInput, 2, expected, 0, expected.length);
assertArrayEquals("Monitor read wrong binary content.", expected, data);
assertArrayEquals("Failed to access buffered binary content twice.", data, monitor.getData());
assertArrayEquals("Wrong binary content through listener.", byteInput, notifiedBytes.toByteArray());
} finally {
sysout.close();
monitor.close();
}
}
/**
* Simple test for output stream monitor. Test listeners without buffering.
*/
@Test
public void testUnbufferedOutputStreamMonitor() throws Exception {
String input = "o\u00F6O";
byte[] byteInput = input.getBytes(StandardCharsets.UTF_8);
try {
monitor.addBinaryListener(fBinaryListener);
monitor.addListener(fStreamListener);
sysout.write(byteInput, 0, 2);
sysout.flush();
monitor.setBuffered(false);
monitor.startMonitoring();
TestUtil.waitWhile(() -> notifiedBytes.size() < 2, 1000);
assertEquals("Monitor read wrong content.", input.substring(0, 1), notifiedChars.toString());
byte[] expected = new byte[2];
System.arraycopy(byteInput, 0, expected, 0, 2);
assertArrayEquals("Monitor read wrong binary content.", expected, notifiedBytes.toByteArray());
monitor.flushContents();
sysout.write(byteInput, 2, byteInput.length - 2);
sysout.flush();
TestUtil.waitWhile(() -> notifiedBytes.size() < byteInput.length, 1000);
assertEquals("Wrong content through listener.", input, notifiedChars.toString());
expected = new byte[byteInput.length - 2];
System.arraycopy(byteInput, 2, expected, 0, expected.length);
assertArrayEquals("Wrong binary content through listener.", byteInput, notifiedBytes.toByteArray());
} finally {
sysout.close();
monitor.close();
}
}
/**
* Test that passing <code>null</code> as charset does not raise exceptions.
*/
@Test
public void testNullCharset() throws Exception {
String input = "o\u00F6O\u00EFiI\u00D6\u00D8\u00F8";
monitor.addListener(fStreamListener);
monitor.startMonitoring();
try (PrintStream out = new PrintStream(sysout)) {
out.print(input);
}
sysout.flush();
TestUtil.waitWhile(() -> notifiedChars.length() < input.length(), 500);
assertEquals("Monitor read wrong content.", input, notifiedChars.toString());
}
/**
* {@link OutputStreamMonitor} with public {@link #startMonitoring()} for
* testing.
*/
private static class TestOutputStreamMonitor extends OutputStreamMonitor {
public TestOutputStreamMonitor(InputStream stream, Charset charset) {
super(stream, charset);
}
@Override
public void startMonitoring() {
super.startMonitoring();
}
@Override
public void close() {
super.close();
}
}
}