| /******************************************************************************* |
| * 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(); |
| } |
| } |
| } |