blob: 056e8402a1bbd33533e2887714456c150361c460 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}