| /******************************************************************************* |
| * Copyright (c) 2019, 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.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNotSame; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.io.IOException; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.debug.tests.TestUtil; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IDocumentPartitioner; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.ITypedRegion; |
| import org.eclipse.jface.text.Region; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.ST; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.ui.console.IConsoleDocumentPartitioner; |
| import org.eclipse.ui.console.IOConsole; |
| import org.eclipse.ui.console.IOConsoleOutputStream; |
| |
| /** |
| * Utility to help testing input and output in {@link IOConsole}. |
| */ |
| public final class IOConsoleTestUtil { |
| /** The tested console. */ |
| private final IOConsole console; |
| /** Document of the tested console. */ |
| private final IDocument doc; |
| /** Text widget of the tested console. */ |
| private final StyledText textPanel; |
| /** The tested consoles document partitioner. */ |
| private final IConsoleDocumentPartitioner partitioner; |
| /** Valid partition types of the used document partitioner. */ |
| private final List<String> validPartionTypes; |
| /** Name used for some logging purpose. */ |
| private final String name; |
| /** |
| * The default output stream used to simulate output in console. Lazy |
| * initialized. |
| */ |
| private IOConsoleOutputStream defaultOut = null; |
| /** |
| * This utility was initial written to be used with disabled fixed width |
| * console. If fixed width is enabled some methods like 'set caret to line |
| * end' may behave unexpected if a test case was written with non fixed |
| * width console in mind. |
| * <p> |
| * If this field is set to <code>true</code> all methods which may behave |
| * problematic in fixed width are executed in a way so that there result is |
| * the same as if the console has no fixed width enabled. E.g. 'set caret to |
| * line end' ignores virtual line wraps and jumps to the next real line |
| * delimiter. |
| * </p> |
| * <p> |
| * If this field is set to <code>true</code> any test written for non fixed |
| * width mode should succeed regardless of the fixed width setting. |
| * </p> |
| */ |
| private boolean ignoreFixedConsole = false; |
| |
| /** |
| * Create a new testing helper. |
| * |
| * @param console the console to test |
| * @param textPanel the consoles text widget. May be <code>null</code> but |
| * none of the user input or caret movement methods can be used |
| * in this case. |
| * @param name name of the caller which will be logged as prefix if some job |
| * waiting timed out. |
| */ |
| public IOConsoleTestUtil(IOConsole console, StyledText textPanel, String name) { |
| this.console = console; |
| assertNotNull(this.console); |
| this.doc = console.getDocument(); |
| assertNotNull(this.doc); |
| final Class<?> expectedInterface = IConsoleDocumentPartitioner.class; |
| assertTrue("Expected partitioner implements " + expectedInterface.getName() + // |
| ". Found: " + this.doc.getDocumentPartitioner().getClass(), // |
| expectedInterface.isAssignableFrom(this.doc.getDocumentPartitioner().getClass())); |
| this.partitioner = (IConsoleDocumentPartitioner) this.doc.getDocumentPartitioner(); |
| this.validPartionTypes = Arrays.asList(this.partitioner.getLegalContentTypes()); |
| this.textPanel = textPanel; |
| this.name = name; |
| } |
| |
| /** |
| * Clear console. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil clear() throws Exception { |
| console.clearConsole(); |
| flush(); |
| assertEquals("Console is not cleared.", 0, doc.getLength()); |
| return this; |
| } |
| |
| /** |
| * Simulate {@link IOConsole} received input from connected processes output |
| * stream but do not wait until input was actually written to console. |
| * |
| * @param s content to write in output stream |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see #write(String) |
| * @see #flush() |
| */ |
| @SuppressWarnings("resource") |
| public IOConsoleTestUtil writeFast(final String s) throws IOException { |
| return writeFast(s, getDefaultOutputStream()); |
| } |
| |
| /** |
| * Simulate {@link IOConsole} received input from connected processes output |
| * stream and wait until content actually arrived in console. |
| * |
| * @param s content to write in output stream |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see #writeFast(String) |
| */ |
| @SuppressWarnings("resource") |
| public IOConsoleTestUtil write(final String s) throws Exception { |
| return write(s, getDefaultOutputStream()); |
| } |
| |
| /** |
| * Simulate {@link IOConsole} received input from connected processes output |
| * stream and verify new console content and partitioning. Expects written |
| * string was appended to end of previous console content and has not |
| * overwritten or removed any previous content. Further expects that |
| * partitioning of new written content is not mixed with other partition |
| * types. |
| * |
| * @param s content to write in output stream |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| @SuppressWarnings("resource") |
| public IOConsoleTestUtil writeAndVerify(final String s) throws Exception { |
| return writeAndVerify(s, getDefaultOutputStream()); |
| } |
| |
| /** |
| * Simulate {@link IOConsole} received input from connected processes output |
| * stream but do not wait until input was actually written to console. |
| * |
| * @param s content to write in output stream |
| * @param out use this output stream instead of default one |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see #write(String, IOConsoleOutputStream) |
| * @see #flush() |
| */ |
| public IOConsoleTestUtil writeFast(final String s, IOConsoleOutputStream out) throws IOException { |
| out.write(s); |
| return this; |
| } |
| |
| /** |
| * Simulate {@link IOConsole} received input from connected processes output |
| * stream and wait until content actually arrived in console. |
| * |
| * @param s content to write in output stream |
| * @param out use this output stream instead of default one |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see #writeFast(String, IOConsoleOutputStream) |
| */ |
| public IOConsoleTestUtil write(final String s, IOConsoleOutputStream out) throws Exception { |
| writeFast(s, out); |
| flush(); |
| return this; |
| } |
| |
| /** |
| * Simulate {@link IOConsole} received input from connected processes output |
| * stream and verify new console content and partitioning. Expects written |
| * string was appended to end of previous console content and has not |
| * overwritten or removed any previous content. Further expects that |
| * partitioning of new written content is not mixed with other partition |
| * types. |
| * |
| * @param s content to write in output stream |
| * @param out use this output stream instead of default one |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil writeAndVerify(final String s, IOConsoleOutputStream out) throws Exception { |
| final int oldLength = doc.getLength(); |
| write(s, out); |
| assertEquals("Console content length not as expected.", oldLength + s.length(), doc.getLength()); |
| verifyContentByOffset(s, oldLength); |
| verifyOutputPartitions(oldLength, s.length()); |
| return this; |
| } |
| |
| /** |
| * Simulate user input. This method is similar to user pasting some content |
| * in console but may not be equal in some case. Especially caret movement |
| * can be different in so use with care. |
| * |
| * @param content string to insert in console |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see #insertTyping(String) |
| */ |
| public IOConsoleTestUtil insert(String content) { |
| final int oldCaretOffset = getCaretOffset(); |
| final int oldSelectionLength = textPanel.getSelectionCount(); |
| final Event e = new Event(); |
| e.start = oldCaretOffset - oldSelectionLength; |
| e.end = oldCaretOffset; |
| e.text = content; |
| e.doit = true; |
| textPanel.notifyListeners(SWT.Verify, e); |
| if (e.doit) { |
| textPanel.replaceTextRange(e.start, e.end - e.start, e.text); |
| // replace does not move caret itself but when a real user paste |
| // content the caret is updated |
| setCaretOffset(e.start + content.length()); |
| } |
| TestUtil.waitForJobs(name, 0, 1000); |
| return this; |
| } |
| |
| /** |
| * Simulate user input and verify the resulting content. This method is |
| * similar to user pasting some content in console but not equal in some |
| * case. Especially caret movement is different in some cases so use with |
| * care. |
| * <p> |
| * The verification expects the content is written at current caret offset, |
| * so do not use if caret is magically moved. (e.g. if insert starts in |
| * read-only part) |
| * </p> |
| * |
| * @param content string to insert in console |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see #insertTypingAndVerify(String) |
| */ |
| public IOConsoleTestUtil insertAndVerify(String content) { |
| final int oldLength = doc.getLength(); |
| final int oldSelectionLength = textPanel.getSelectionCount(); |
| final int oldOffset = getCaretOffset() - oldSelectionLength; |
| insert(content); |
| assertEquals("Console content length not as expected.", oldLength + content.length() - oldSelectionLength, doc.getLength()); |
| assertEquals("Caret not at expected position.", oldOffset + content.length(), getCaretOffset()); |
| verifyContentByOffset(content, oldOffset); |
| verifyInputPartitions(oldOffset, content.length()); |
| return this; |
| } |
| |
| /** |
| * Simulate user typing some text in console. This method simulates |
| * keystrokes and therefore tests console behavior quite realistic. |
| * <p> |
| * Note: typing <code>\n</code> may result in platform dependent line |
| * delimiter entered. Also <code>\r\n</code> is typed as two separate |
| * characters and therefore leads to two line breaks. |
| * </p> |
| * |
| * @param content string to insert in console |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see #insert(String) |
| */ |
| public IOConsoleTestUtil insertTyping(String content) { |
| for (char c : content.toCharArray()) { |
| final Event e = new Event(); |
| e.character = c; |
| textPanel.notifyListeners(SWT.KeyDown, e); |
| textPanel.notifyListeners(SWT.KeyUp, e); |
| } |
| TestUtil.waitForJobs(name, 0, 1000); |
| return this; |
| } |
| |
| /** |
| * Simulate user typing some text in console and check results. This method |
| * simulates keystrokes and therefore tests console behavior quite |
| * realistic. |
| * <p> |
| * Note: typing <code>\n</code> may result in platform dependent line |
| * delimiter entered. Also <code>\r\n</code> is typed as two separate |
| * characters and therefore leads to two line breaks. |
| * </p> |
| * |
| * @param content string to insert in console |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see #insertAndVerify(String) |
| */ |
| public IOConsoleTestUtil insertTypingAndVerify(String content) { |
| final int oldLength = doc.getLength(); |
| final int oldSelectionLength = textPanel.getSelectionCount(); |
| final int oldOffset = getCaretOffset() - oldSelectionLength; |
| insertTyping(content); |
| assertEquals("Console content length not as expected.", oldLength + content.length() - oldSelectionLength, doc.getLength()); |
| assertEquals("Caret not at expected position.", oldOffset + content.length(), getCaretOffset()); |
| verifyContentByOffset(content, oldOffset); |
| verifyInputPartitions(oldOffset, content.length()); |
| return this; |
| } |
| |
| /** |
| * Simulate user pressing backspace. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil backspace() { |
| return backspace(1); |
| } |
| |
| /** |
| * Simulate user pressing backspace multiple times. |
| * |
| * @param repeat perform this many backspaces |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil backspace(int repeat) { |
| for (int i = 0; i < repeat; i++) { |
| if (ignoreFixedConsole) { |
| // Note: this backspace simulation can not handle multibyte line |
| // delimiter. It would only delete one byte with one backspace. |
| final Event e = new Event(); |
| e.doit = true; |
| e.text = ""; |
| final IRegion selection = getSelection(); |
| if (selection.getLength() == 0) { |
| final int caretOffset = getCaretOffset(); |
| e.start = caretOffset - 1; |
| e.end = caretOffset; |
| if (caretOffset <= 0) { |
| e.doit = false; |
| } |
| } else { |
| e.start = selection.getOffset(); |
| e.end = selection.getOffset() + selection.getLength(); |
| } |
| if (e.doit) { |
| textPanel.notifyListeners(SWT.Verify, e); |
| } |
| if (e.doit) { |
| textPanel.replaceTextRange(e.start, e.end - e.start, e.text); |
| setCaretOffset(e.start); |
| } |
| } else { |
| textPanel.invokeAction(ST.DELETE_PREVIOUS); |
| } |
| } |
| return this; |
| } |
| |
| /** |
| * Simulate user pressing enter. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil enter() { |
| // Note: newline will be replaced by |
| // System.lineSeparator() so do not assume document length |
| // will increase by 1 |
| insertTyping("\n"); |
| return this; |
| } |
| |
| /** |
| * Current caret position in console. |
| * |
| * @return current caret position in console |
| * @see StyledText#getCaretOffset() |
| */ |
| public int getCaretOffset() { |
| return textPanel.getCaretOffset(); |
| } |
| |
| /** |
| * Set caret to new position. |
| * |
| * @param offset new caret position |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see StyledText#setCaretOffset(int) |
| */ |
| public IOConsoleTestUtil setCaretOffset(int offset) { |
| textPanel.setCaretOffset(offset); |
| return this; |
| } |
| |
| /** |
| * Set caret to offset relative to start of current line. |
| * |
| * @param offset relative offset to line start |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil setCaretLineRelative(int offset) { |
| moveCaretToLineStart().moveCaret(offset); |
| return this; |
| } |
| |
| /** |
| * Move caret by given amount forth or back. |
| * |
| * @param amount steps to set caret forth (positive value) or back (negative |
| * value) |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil moveCaret(int amount) { |
| setCaretOffset(getCaretOffset() + amount); |
| return this; |
| } |
| |
| /** |
| * Move caret to start of console content. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil moveCaretToStart() { |
| textPanel.invokeAction(ST.TEXT_START); |
| return this; |
| } |
| |
| /** |
| * Move caret to end of console content. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil moveCaretToEnd() { |
| textPanel.invokeAction(ST.TEXT_END); |
| return this; |
| } |
| |
| /** |
| * Move caret to start of its current line. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil moveCaretToLineStart() { |
| if (ignoreFixedConsole) { |
| try { |
| final int currentOffset = getCaretOffset(); |
| final int docLineStart = getDocument().getLineInformationOfOffset(currentOffset).getOffset(); |
| setCaretOffset(docLineStart); |
| } catch (BadLocationException e) { |
| TestUtil.log(IStatus.ERROR, name, "Failed to set caret to line start in wrapped line mode.", e); |
| } |
| } else { |
| textPanel.invokeAction(ST.LINE_START); |
| } |
| return this; |
| } |
| |
| /** |
| * Move caret to end of its current line. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil moveCaretToLineEnd() { |
| if (ignoreFixedConsole) { |
| try { |
| final int currentOffset = getCaretOffset(); |
| final IRegion docLine = getDocument().getLineInformationOfOffset(currentOffset); |
| setCaretOffset(docLine.getOffset() + docLine.getLength()); |
| } catch (BadLocationException e) { |
| TestUtil.log(IStatus.ERROR, name, "Failed to set caret to line end in wrapped line mode.", e); |
| } |
| } else { |
| textPanel.invokeAction(ST.LINE_END); |
| } |
| return this; |
| } |
| |
| /** |
| * Get the selected text region in console. |
| * |
| * @return the selected region |
| */ |
| public IRegion getSelection() { |
| final Point selection = textPanel.getSelection(); |
| return new Region(selection.x, selection.y - selection.x); |
| } |
| |
| /** |
| * Select text in console. |
| * |
| * @param offset selection start position. May be negative to select |
| * relative from document end. |
| * @param length selection length |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see StyledText#setSelection(int, int) |
| */ |
| public IOConsoleTestUtil select(int offset, int length) { |
| final int o = offset < 0 ? doc.getLength() + offset : offset; |
| setCaretOffset(o + length); |
| textPanel.setSelectionRange(o, length); |
| return this; |
| } |
| |
| /** |
| * Select all content in console. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see StyledText#setSelection(int, int) |
| */ |
| public IOConsoleTestUtil selectAll() { |
| textPanel.selectAll(); |
| return this; |
| } |
| |
| /** |
| * Check if console content equals the expected content. |
| * |
| * @param expectedContent content expect in console |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil verifyContent(String expectedContent) { |
| verifyContentByOffset(expectedContent, 0); |
| assertEquals("More or less content in console as expected.", expectedContent.length(), doc.getLength()); |
| return this; |
| } |
| |
| /** |
| * Check if line in console has expected content. |
| * |
| * @param expectedContent content expect in console |
| * @param lineNum the line in console to check. First line has number |
| * <code>0</code>. Accepts negative numbers as line relative to |
| * console end. |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil verifyContentByLine(String expectedContent, int lineNum) { |
| final int l = lineNum < 0 ? doc.getNumberOfLines() + lineNum : lineNum; |
| try { |
| final IRegion line = doc.getLineInformation(l); |
| verifyContentByOffset(expectedContent, line.getOffset()); |
| assertEquals("Line " + l + " has wrong length.", expectedContent.length(), line.getLength()); |
| } catch (BadLocationException e) { |
| fail("Expected line " + lineNum + " not found in console document. Bad location!"); |
| } |
| return this; |
| } |
| |
| /** |
| * Check if console contains expected content at given offset. |
| * |
| * @param expectedContent content expect in console |
| * @param offset position where content is expected. If offset is negative |
| * it will be interpreted as relative to document end. |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil verifyContentByOffset(String expectedContent, int offset) { |
| try { |
| final int o = offset < 0 ? doc.getLength() + offset : offset; |
| final int len = Math.min(doc.getLength() - o, expectedContent.length()); |
| assertEquals("Expected string not found in console document.", expectedContent, doc.get(o, len)); |
| } catch (BadLocationException ex) { |
| fail("Expected string '" + expectedContent + "' not found in console document. Bad location!"); |
| } |
| return this; |
| } |
| |
| /** |
| * Check if console range is partitioned only by output partitions. |
| * |
| * @param offset range start |
| * @param length range length |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil verifyOutputPartitions(int offset, int length) { |
| return verifyPartitions(offset, length, outputPartitionType(), false, false, 0); |
| } |
| |
| /** |
| * Check if console range is partitioned only by input partitions. |
| * |
| * @param offset range start |
| * @param length range length |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil verifyInputPartitions(int offset, int length) { |
| return verifyPartitions(offset, length, inputPartitionType(), false, false, 0); |
| } |
| |
| /** |
| * Check if whole console document is partitioned. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil verifyPartitions() { |
| return verifyPartitions(0); |
| } |
| |
| /** |
| * Check if whole console document is partitioned. |
| * |
| * @param minPartitionNumber the minimum number of partitions expected |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil verifyPartitions(int minPartitionNumber) { |
| return verifyPartitions(0, doc.getLength(), null, true, false, minPartitionNumber); |
| } |
| |
| /** |
| * Check partitioning of console range. |
| * |
| * @param offset range start |
| * @param length range length |
| * @param expectedType either all partitions in checked ranges are expected |
| * to be of this type or <code>null</code> to not force type |
| * @param allowMixedTypes if true range may comprised from all partition |
| * types. If false all partitions in range must be of same type. |
| * @param allowGaps if false |
| * {@link IDocumentPartitioner#computePartitioning(int, int)} |
| * must not contain any unpartitioned parts |
| * @param minPartitionNumber the minimum number of partitions expected |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| * @see IDocumentPartitioner#computePartitioning(int, int) |
| * @see IDocumentPartitioner#getPartition(int) |
| */ |
| public IOConsoleTestUtil verifyPartitions(final int offset, final int length, final String expectedType, final boolean allowMixedTypes, final boolean allowGaps, int minPartitionNumber) { |
| { |
| final ITypedRegion[] partitions = getPartitioner().computePartitioning(offset, length); |
| assertNotNull("Got no partitions.", partitions); |
| assertTrue("Got less partitions than expected.", partitions.length >= minPartitionNumber); |
| |
| // points to offset after last partition range aka. expected start |
| // of next partition |
| int lastEnd = -1; |
| ITypedRegion lastPartition = null; |
| String partitionType = expectedType; |
| for (ITypedRegion partition : partitions) { |
| assertNotSame("Got same partition twice.", lastPartition, partition); |
| assertTrue("Partition overlapping. (or not sorted as expected)", partition.getOffset() >= lastEnd); |
| if (!allowGaps && lastEnd != -1) { |
| assertTrue("Partitioning gap.", partition.getOffset() == lastEnd); |
| } |
| assertTrue("Not a valid partition type.", validPartionTypes.contains(partition.getType())); |
| assertTrue("Wrong partition type.", partitionType == null || partitionType.equals(partition.getType()) || allowMixedTypes); |
| if (partitionType == null && !allowMixedTypes) { |
| partitionType = partition.getType(); |
| } |
| lastEnd = partition.getOffset() + partition.getLength(); |
| lastPartition = partition; |
| } |
| } |
| int pos = offset; |
| int end = offset + length; |
| ITypedRegion lastPartition = null; |
| String partitionType = expectedType; |
| while (pos < end) { |
| final ITypedRegion partition = getPartitioner().getPartition(pos); |
| if (partition == null) { |
| assertTrue("Did not expect 'null' partition.", allowGaps); |
| pos++; |
| continue; |
| } |
| assertNotSame("Got same partition again.", lastPartition, partition); |
| assertFalse("Did not expected and cannot handle empty partition.", partition.getLength() == 0); |
| assertTrue("Got not the requested partition.", partition.getOffset() <= pos && partition.getOffset() + partition.getLength() > pos); |
| assertTrue("Not a valid partition type.", validPartionTypes.contains(partition.getType())); |
| lastPartition = partition; |
| if (partitionType != null && !partitionType.equals(partition.getType())) { |
| assertTrue("Wrong partition type.", allowMixedTypes); |
| pos += partition.getLength(); |
| end += partition.getLength(); |
| continue; |
| } |
| if (partitionType == null && !allowMixedTypes) { |
| partitionType = partition.getType(); |
| } |
| pos = partition.getOffset() + partition.getLength(); |
| } |
| return this; |
| } |
| |
| /** |
| * Wait for waiting or scheduled jobs. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil waitForScheduledJobs() { |
| boolean jobSleeping = false; |
| for (int i = 0; i < 5 && !jobSleeping; i++) { |
| final boolean jobPending = TestUtil.waitForJobs(name, 25, 2000); |
| if (!jobPending) { |
| jobSleeping = false; |
| for (Job job : TestUtil.getRunningOrWaitingJobs(null)) { |
| if (job.getState() == Job.SLEEPING) { |
| jobSleeping = true; |
| break; |
| } |
| } |
| } |
| } |
| return this; |
| } |
| |
| /** |
| * Ensure all pending write operations are fully applied on the console view |
| * before returning. |
| * |
| * @return this {@link IOConsoleTestUtil} to chain methods |
| */ |
| public IOConsoleTestUtil flush() { |
| // overall this method is just a better name for waitForScheduledJobs |
| waitForScheduledJobs(); |
| return this; |
| } |
| |
| /** |
| * Close the default output stream if it was used. |
| */ |
| public void closeOutputStream() { |
| if (defaultOut != null) { |
| try { |
| defaultOut.close(); |
| } catch (IOException e) { |
| fail("Failed to close output stream."); |
| } |
| } |
| } |
| |
| /** |
| * Get length of current console content. |
| * |
| * @return consoles document length |
| */ |
| public int getContentLength() { |
| return getDocument().getLength(); |
| } |
| |
| public IOConsole getConsole() { |
| return console; |
| } |
| |
| public IDocument getDocument() { |
| return doc; |
| } |
| |
| public IConsoleDocumentPartitioner getPartitioner() { |
| return partitioner; |
| } |
| |
| public IOConsoleOutputStream getDefaultOutputStream() { |
| if (defaultOut == null) { |
| defaultOut = console.newOutputStream(); |
| } |
| return defaultOut; |
| } |
| |
| /** |
| * If <code>true</code> the util will work as if console is not in fixed |
| * width mode. E.g. {@link #moveCaretToLineStart()} will move caret to |
| * document line start not to widget line start or |
| * {@link #verifyContentByLine(String, int)} would check the line as seen |
| * without fixed width. |
| * |
| * @see #ignoreFixedConsole |
| */ |
| public boolean isIgnoreFixedConsole() { |
| return ignoreFixedConsole; |
| } |
| |
| /** |
| * Enable compatibility mode. If set to <code>true</code> tests written for |
| * console without fixed width should work with any fixed width. Commands |
| * like {@link #moveCaretToLineStart()} are modified to not move to begin of |
| * widget line (maybe wrapped line) but to start it would have without fixed |
| * width or {@link #verifyContentByLine(String, int)} would check the line |
| * as seen without fixed width. |
| * |
| * @see #ignoreFixedConsole |
| */ |
| public void setIgnoreFixedConsole(boolean ignoreWrappeding) { |
| this.ignoreFixedConsole = ignoreWrappeding; |
| } |
| |
| /** |
| * Get identifier for output {@link IOConsolePartition}s. |
| * |
| * @return output partition identifier |
| */ |
| @SuppressWarnings("restriction") |
| public static String outputPartitionType() { |
| return org.eclipse.ui.internal.console.IOConsolePartition.OUTPUT_PARTITION_TYPE; |
| } |
| |
| /** |
| * Get identifier for input {@link IOConsolePartition}s. |
| * |
| * @return input partition identifier |
| */ |
| @SuppressWarnings("restriction") |
| public static String inputPartitionType() { |
| return org.eclipse.ui.internal.console.IOConsolePartition.INPUT_PARTITION_TYPE; |
| } |
| } |