/*******************************************************************************
 * Copyright (c) 2014, 2020 SAP SE 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:
 *     SAP SE - initial API and implementation
 *     Paul Pazderski - Bug 546900: Tests to check initial console content and content persistence
 *     Paul Pazderski - Bug 343023: Tests for 'clear initial content on first edit'
 *     Paul Pazderski - Bug 304219: Tests for formatting
 *******************************************************************************/
package org.eclipse.jdt.debug.tests.console;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNotEquals;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.debug.tests.AbstractDebugTest;
import org.eclipse.jdt.debug.tests.TestUtil;
import org.eclipse.jdt.debug.ui.console.JavaStackTraceConsoleFactory;
import org.eclipse.jdt.internal.debug.ui.console.ConsoleMessages;
import org.eclipse.jdt.internal.debug.ui.console.JavaStackTraceConsole;
import org.eclipse.jdt.internal.debug.ui.console.JavaStackTraceConsolePage;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ST;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.TextConsoleViewer;
import org.eclipse.ui.internal.console.ConsoleHyperlinkPosition;
import org.eclipse.ui.internal.console.ConsoleView;

/**
 * Tests {@link JavaStackTraceConsole}
 */
public class JavaStackTraceConsoleTest extends AbstractDebugTest {

	private final static Pattern LEFT_INDENT = Pattern.compile("^[ \\t]*");
	private final static Pattern RIGHT_INDENT = Pattern.compile("\\s+$");

	private final JavaStackTraceConsoleFactory fConsoleFactory = new JavaStackTraceConsoleFactory();
	private JavaStackTraceConsole fConsole;

	public JavaStackTraceConsoleTest(String name) {
		super(name);
	}

	@Override
	public void setUp() throws Exception {
		super.setUp();
		initConsole(true);
	}

	@Override
	protected void tearDown() throws Exception {
		removeConsole(false);
		super.tearDown();
	}

	/**
	 * Create and register a {@link JavaStackTraceConsole}.
	 *
	 * @param assertDefaultContent
	 *            If <code>true</code> assert console is initialized with its default content.
	 * @see #removeConsole(boolean)
	 */
	private void initConsole(boolean assertDefaultContent) {
		fConsoleFactory.openConsole();
		IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();
		IConsole[] consoles = consoleManager.getConsoles();
		fConsole = null;
		for (IConsole console : consoles) {
			if (console instanceof JavaStackTraceConsole) {
				fConsole = (JavaStackTraceConsole) console;
				// do not end loop. There should be only one JavaStackTraceConsole but if there are more
				// the last one is most likely the one we opened
			}
		}
		assertNotNull("Failed to open a JavaStackTraceConsole", fConsole);
		if (assertDefaultContent) {
			assertInitialContent();
		}
	}

	/**
	 * Remove the previous created console.
	 *
	 * @param preserveContent
	 *            If <code>true</code> the remove does not prevent the current console content from being loaded by next
	 *            {@link JavaStackTraceConsole}.
	 * @see #initConsole(boolean)
	 */
	private void removeConsole(boolean preserveContent) {
		if (!preserveContent) {
			fConsole.clearConsole();
		}
		final int contentLength = fConsole.getDocument().getLength();

		IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();
		consoleManager.removeConsoles(new IConsole[] { fConsole });

		final Path stackTraceFile = Paths.get(JavaStackTraceConsole.FILE_NAME);
		if (!preserveContent) {
			assertTrue("Leaked content of JavaStackTraceConsole", Files.notExists(stackTraceFile));
		} else {
			assertTrue("JavaStackTraceConsole content was not persisted", Files.exists(stackTraceFile));
			try {
				assertTrue("Persisted content seems incomplete", Files.size(stackTraceFile) >= contentLength);
			} catch (IOException e) {
				fail("Persisted content seems incomplete");
			}
		}
	}

	public void testHyperlinkMatchSignatureSimple() throws Exception {
		consoleDocumentWithText("at foo.bar.Type.method1(Type.java:1)");

		String[] matchTexts = linkTextsAtPositions(24);
		assertArrayEquals(allLinks(), new String[] { "Type.java:1" }, matchTexts);
	}

	public void testHyperlinkMatchSignatureExtended() throws Exception {
		consoleDocumentWithText("at foo.bar.Type.method1(IILjava/lang/String;)V(Type.java:1)");

		String[] matchTexts = linkTextsAtPositions(47);
		assertArrayEquals(allLinks(), new String[] { "Type.java:1" }, matchTexts);
	}

	public void testHyperlinkMatchMultiple() throws Exception {
		consoleDocumentWithText("at foo.bar.Type.method2(Type.java:2)\n" //
				+ "at foo.bar.Type.method1(Type.java:1)");

		String[] matchTexts = linkTextsAtPositions(24, 61);
		assertArrayEquals(allLinks(), new String[] { "Type.java:2", "Type.java:1" }, matchTexts);
	}

	public void testHyperlinkMatchInvalidLine() throws Exception {
		consoleDocumentWithText("at foo.bar.Type.method1(Type.java:fff)");

		String[] matchTexts = linkTextsAtPositions(24);
		assertArrayEquals(allLinks(), new String[] { "Type.java:fff" }, matchTexts);
	}

	public void testHyperlinkNoMatch() throws Exception {
		consoleDocumentWithText("at foo.bar.Type.method1(foo.bar.Type.java:42)");

		Position[] positions = allLinkPositions();
		assertArrayEquals("Expected no hyperlinks for invalid type name", new Position[0], positions);
	}

	/**
	 * Test save/restore of stack trace console content on console close/reactivation.
	 */
	public void testLoadAndSaveDocument() throws Exception {
		IDocument initialDocument = fConsole.getDocument();
		String storedContent = "at foo.bar.Type.method1(Type.java:fff)";
		consoleDocumentWithText(storedContent);
		removeConsole(true);

		Path file = Paths.get(JavaStackTraceConsole.FILE_NAME);
		assertTrue("Content was not stored.", Files.exists(file));
		assertTrue("Content was not stored.", Files.size(file) > 0);

		initConsole(false);
		assertNotSame("Failed to create new console.", initialDocument, fConsole.getDocument());
		assertEquals("Failed to restore previous content.", storedContent, fConsole.getDocument().get());
	}

	/**
	 * Test for Bug 343023. Test if initial content is cleared on first edit and not cleared if it was changed programmatically before.
	 */
	public void testClearInitialContent() {
		PlatformUI.getWorkbench().getDisplay().syncExec(() -> {
			// type at start of initial content
			TextConsoleViewer viewer = getConsolesViewer();
			viewer.getTextWidget().invokeAction(ST.TEXT_START);
			doKeyStroke(viewer.getTextWidget(), 'a');
			assertEquals("Initial content was not cleared.", "a", fConsole.getDocument().get());
			doKeyStroke(viewer.getTextWidget(), 'b');
			assertEquals("Content was cleared again.", "ab", fConsole.getDocument().get());
			removeConsole(false);

			// type inside initial content
			initConsole(true);
			viewer = getConsolesViewer();
			viewer.getTextWidget().setCaretOffset(5);
			doKeyStroke(viewer.getTextWidget(), 'a');
			assertEquals("Initial content was not cleared.", "a", fConsole.getDocument().get());
			doKeyStroke(viewer.getTextWidget(), 'b');
			assertEquals("Content was cleared again.", "ab", fConsole.getDocument().get());
			removeConsole(false);

			// type at end of initial content
			initConsole(true);
			viewer = getConsolesViewer();
			viewer.getTextWidget().invokeAction(ST.TEXT_END);
			doKeyStroke(viewer.getTextWidget(), 'a');
			assertEquals("Initial content was not cleared.", "a", fConsole.getDocument().get());
			doKeyStroke(viewer.getTextWidget(), 'b');
			assertEquals("Content was cleared again.", "ab", fConsole.getDocument().get());
			removeConsole(false);

			// select all initial content
			initConsole(true);
			viewer = getConsolesViewer();
			viewer.getTextWidget().selectAll();
			doKeyStroke(viewer.getTextWidget(), 'a');
			assertEquals("Initial content was not cleared.", "a", fConsole.getDocument().get());
			doKeyStroke(viewer.getTextWidget(), 'b');
			assertEquals("Content was cleared again.", "ab", fConsole.getDocument().get());
			removeConsole(false);

			// select part of initial content
			initConsole(true);
			viewer = getConsolesViewer();
			viewer.getTextWidget().setSelection(5, 10);
			doKeyStroke(viewer.getTextWidget(), 'a');
			assertEquals("Initial content was not cleared.", "a", fConsole.getDocument().get());
			doKeyStroke(viewer.getTextWidget(), 'b');
			assertEquals("Content was cleared again.", "ab", fConsole.getDocument().get());
			removeConsole(false);

			// paste inside initial content
			initConsole(true);
			viewer = getConsolesViewer();
			viewer.getTextWidget().setCaretOffset(5);
			viewer.getTextWidget().insert("at foo.bar.Type.method1(IILjava/lang/String;)V(Type.java:1)");
			assertEquals("Initial content was not cleared.", "at foo.bar.Type.method1(IILjava/lang/String;)V(Type.java:1)", fConsole.getDocument().get());
			doKeyStroke(viewer.getTextWidget(), 'b');
			assertTrue("Content was cleared again.", fConsole.getDocument().getLength() > 5);
			removeConsole(false);

			// user edit after something already modified the content (expect no magic clear)
			initConsole(true);
			viewer = getConsolesViewer();
			String text = "Text set programmatically";
			viewer.getTextWidget().setText(text);
			viewer.getTextWidget().invokeAction(ST.TEXT_END);
			doKeyStroke(viewer.getTextWidget(), '!');
			assertEquals(text + "!", fConsole.getDocument().get());
			removeConsole(true); // preserve content this time!

			// check first edit does not clear if console is initialized with custom content
			initConsole(false);
			viewer = getConsolesViewer();
			int lengthBefore = fConsole.getDocument().getLength();
			doKeyStroke(viewer.getTextWidget(), 'a');
			assertEquals("Custom content was cleared.", lengthBefore + 1, fConsole.getDocument().getLength());
			// do not remove last console so tearDown can do something
		});
	}

	/** Test formatting of a plain simple stack trace. */
	public void testFormatSimple() {
		IDocument doc = consoleDocumentFormatted("java.lang.AssertionError: expected:5 but was:7\n\n"
				+ "at org.junit.Ass\nert.fail(Assert.java:88) \n" + "at\norg.junit.   \nAssert.failNotEquals(Assert.java:834)\n"
				+ "at org.junit.Assert.assertEquals(Assert.java:118)\n" + "at \norg.junit.Assert.assertEquals\n(Assert.java:144)");
		assertEquals("java.lang.AssertionError: expected:5 but was:7", getLine(doc, 0));
		assertEquals("at org.junit.Assert.fail(Assert.java:88)", getLine(doc, 1).trim());
		assertEquals("at org.junit.Assert.failNotEquals(Assert.java:834)", getLine(doc, 2).trim());
		assertEquals("at org.junit.Assert.assertEquals(Assert.java:118)", getLine(doc, 3).trim());
		assertEquals("at org.junit.Assert.assertEquals(Assert.java:144)", getLine(doc, 4).trim());
		checkIndentationConsistency(doc, 0);
	}

	/** Test formatting of a stack trace including thread name. */
	public void testFormatThreadName() {
		IDocument doc = consoleDocumentFormatted("Exception in thread \"ma\nin\" java.lang.NullPointerException\n"
				+ "at \nStacktrace.main(Stacktrace.java:4)");
		assertEquals("Exception in thread \"main\" java.lang.NullPointerException", getLine(doc, 0));
		assertEquals("at Stacktrace.main(Stacktrace.java:4)", getLine(doc, 1).trim());
		checkIndentationConsistency(doc, 0);
	}

	/** Test formatting with some less common method names. */
	public void testFormatUncommonMethods() {
		IDocument doc = consoleDocumentFormatted("Stack Trace\n" + "  at org.eclipse.core.runtime.SafeRunner.run\n(SafeRunner.java:43)\n"
				+ "      at org.eclipse.ui.internal.JFaceUtil.lambda$0(JFaceUtil.java:47)\n"
				+ "    at org.eclipse.ui.internal.JFaceUtil$$Lambda$107/0x00000   \n008013c5c40.run(Unknown Source)\n"
				+ "\tat org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:174)\n"
				+ "         at java.base@12/java.lang.reflect.Method.invoke(Method.java:567)\n"
				+ " \n at app/\n/org.eclipse.equinox.launcher.Main.main(Main.java:1438)");
		assertEquals("Stack Trace", getLine(doc, 0));
		assertEquals("at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:43)", getLine(doc, 1).trim());
		assertEquals("at org.eclipse.ui.internal.JFaceUtil.lambda$0(JFaceUtil.java:47)", getLine(doc, 2).trim());
		assertEquals("at org.eclipse.ui.internal.JFaceUtil$$Lambda$107/0x00000008013c5c40.run(Unknown Source)", getLine(doc, 3).trim());
		assertEquals("at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:174)", getLine(doc, 4).trim());
		assertEquals("at java.base@12/java.lang.reflect.Method.invoke(Method.java:567)", getLine(doc, 5).trim());
		assertEquals("at app//org.eclipse.equinox.launcher.Main.main(Main.java:1438)", getLine(doc, 6).trim());
		checkIndentationConsistency(doc, 0);
	}

	/** Test formatting with a 'locked' entry. */
	public void testFormatLocked() {
		IDocument doc = consoleDocumentFormatted("java.lang.Thread.State: RUNNABLE\n"
				+ " at java.net.PlainSocketImpl.socketAccept(Native Method)\n\n\n"
				+ "at java.net.PlainSocketImpl\n.accept(PlainSocketImpl.java:408)\n" + "\t - locked <0x911d3c30>   (a java.net.SocksSocketImpl)\n"
				+ "    at java.net.ServerSocket.implAccept(ServerSocket.java:462)\n" + "at java.net.ServerSocket.accept(ServerSocket.java:430)");
		assertEquals("java.lang.Thread.State: RUNNABLE", getLine(doc, 0));
		assertEquals("at java.net.PlainSocketImpl.socketAccept(Native Method)", getLine(doc, 1).trim());
		assertEquals("at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)", getLine(doc, 2).trim());
		assertEquals("- locked <0x911d3c30> (a java.net.SocksSocketImpl)", getLine(doc, 3).trim());
		assertEquals("at java.net.ServerSocket.implAccept(ServerSocket.java:462)", getLine(doc, 4).trim());
		assertEquals("at java.net.ServerSocket.accept(ServerSocket.java:430)", getLine(doc, 5).trim());
		checkIndentationConsistency(doc, 0);
	}

	/** Test formatting with a ... more entry. */
	public void testFormatMore() {
		// additional this one is missing the 'header' line and starting with an 'at' line
		IDocument doc = consoleDocumentFormatted(" at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.preparePersistenceUnitInfos(DefaultPersistenceUnitManager.java:470)\n"
				+ "    at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.afterPropertiesSet(DefaultPersistenceUnitManager.java:424)\n"
				+ "at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:310)\n"
				+ "          at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)\n\n"
				+ "  \t\t    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)\n"
				+ "   \t \tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)\n"
				+ "  ... 53 more\n" + "");
		assertEquals("at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.preparePersistenceUnitInfos(DefaultPersistenceUnitManager.java:470)", getLine(doc, 1).trim());
		assertEquals("at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.afterPropertiesSet(DefaultPersistenceUnitManager.java:424)", getLine(doc, 2).trim());
		assertEquals("at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:310)", getLine(doc, 3).trim());
		assertEquals("at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)", getLine(doc, 4).trim());
		assertEquals("at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)", getLine(doc, 5).trim());
		assertEquals("at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)", getLine(doc, 6).trim());
		assertEquals("... 53 more", getLine(doc, 7).trim());
		checkIndentationConsistency(doc, 0);
	}

	/** Test formatting stack trace with cause. */
	public void testFormatCause() {
		IDocument doc = consoleDocumentFormatted("HighLevelException:\n LowLevelException\n" + "\tat Junk.a(Junk.java:13)\n"
				+ "         at Junk.main(Junk.java:4)\n" + "     Caused by: LowLevelException\n" + " at Junk.e(Junk.java:30)\n"
				+ "    at Junk.d\n(Junk.java:27)\n" + "at Junk.c(Junk.java:21)");
		assertEquals("HighLevelException: LowLevelException", getLine(doc, 0));
		assertEquals("at Junk.a(Junk.java:13)", getLine(doc, 1).trim());
		assertEquals("at Junk.main(Junk.java:4)", getLine(doc, 2).trim());
		assertEquals("Caused by: LowLevelException", getLine(doc, 3));
		assertEquals("at Junk.e(Junk.java:30)", getLine(doc, 4).trim());
		assertEquals("at Junk.d(Junk.java:27)", getLine(doc, 5).trim());
		assertEquals("at Junk.c(Junk.java:21)", getLine(doc, 6).trim());
		checkIndentationConsistency(doc, 0);

		// nested causes
		doc = consoleDocumentFormatted("HighLevelException:\t MidLevelException:\n LowLevelException\n" + "\tat Junk.a(Junk.java:13)\n"
				+ "    at Junk.main(Junk.java:4)\n" + " Caused by: MidLevelException: LowLevelException\n" + "    at Junk.c(Junk.java:23)\n"
				+ "      at Junk.b(Junk.java:17)\n" + "      at Junk.a(Junk.java:11)\n" + "... 1 more\n" + " Caused by: LowLevelException\n"
				+ "     at Junk.e(Junk.java:30)\n" + "at Junk.d(Junk.java:27)\n" + "   at Junk.c(Junk.java:21)\n" + "         ... 3 more\n");
		assertEquals("HighLevelException: MidLevelException: LowLevelException", getLine(doc, 0));
		assertEquals("at Junk.a(Junk.java:13)", getLine(doc, 1).trim());
		assertEquals("at Junk.main(Junk.java:4)", getLine(doc, 2).trim());
		assertEquals("Caused by: MidLevelException: LowLevelException", getLine(doc, 3));
		assertEquals("at Junk.c(Junk.java:23)", getLine(doc, 4).trim());
		assertEquals("at Junk.b(Junk.java:17)", getLine(doc, 5).trim());
		assertEquals("at Junk.a(Junk.java:11)", getLine(doc, 6).trim());
		assertEquals("... 1 more", getLine(doc, 7).trim());
		assertEquals("Caused by: LowLevelException", getLine(doc, 8));
		assertEquals("at Junk.e(Junk.java:30)", getLine(doc, 9).trim());
		assertEquals("at Junk.d(Junk.java:27)", getLine(doc, 10).trim());
		assertEquals("at Junk.c(Junk.java:21)", getLine(doc, 11).trim());
		assertEquals("... 3 more", getLine(doc, 12).trim());
		checkIndentationConsistency(doc, 0);
	}

	/** Test formatting stack trace with suppressed exceptions. */
	public void testFormatSuppressed() {
		IDocument doc = consoleDocumentFormatted("Exception in thread \"main\" java.lang.Exception: Something happened\n" + "at Foo.bar(Native)\n"
				+ "  at Foo.main(Foo.java:5)\n" + "  Suppressed: Resource$CloseFailException: Resource ID = 0\n"
				+ "    at Resource.close(Resource\n.java:26)\n" + "      at Foo.bar(Foo.java)\n" + "         ... 1 more\n" + "");
		assertEquals("Exception in thread \"main\" java.lang.Exception: Something happened", getLine(doc, 0));
		assertEquals("at Foo.bar(Native)", getLine(doc, 1).trim());
		assertEquals("at Foo.main(Foo.java:5)", getLine(doc, 2).trim());
		assertEquals("Suppressed: Resource$CloseFailException: Resource ID = 0", getLine(doc, 3).trim());
		assertEquals("at Resource.close(Resource.java:26)", getLine(doc, 4).trim());
		assertEquals("at Foo.bar(Foo.java)", getLine(doc, 5).trim());
		assertEquals("... 1 more", getLine(doc, 6).trim());
		checkIndentationConsistency(doc, 0);

		// multiple suppressed
		doc = consoleDocumentFormatted("Exception in thread \"main\" java.lang.Exception: Main block\n" + "  at Foo3.main(Foo3.java:7)\n"
				+ "     Suppressed: Resource$CloseFailException: Resource ID = 2\n" + "      at Resource.close(Resource.java:26)\n"
				+ "   \t\tat Foo3.main(Foo3.java:5)\n" + "Suppressed: Resource$CloseFailException: Resource ID = 1\n"
				+ "      at Resource.close(Resource.java:26)\n" + "                at Foo3.main(Foo3.java:5)\n" + "");
		assertEquals("Exception in thread \"main\" java.lang.Exception: Main block", getLine(doc, 0));
		assertEquals("at Foo3.main(Foo3.java:7)", getLine(doc, 1).trim());
		assertEquals("Suppressed: Resource$CloseFailException: Resource ID = 2", getLine(doc, 2).trim());
		assertEquals("at Resource.close(Resource.java:26)", getLine(doc, 3).trim());
		assertEquals("at Foo3.main(Foo3.java:5)", getLine(doc, 4).trim());
		assertEquals("Suppressed: Resource$CloseFailException: Resource ID = 1", getLine(doc, 5).trim());
		assertEquals("at Resource.close(Resource.java:26)", getLine(doc, 6).trim());
		assertEquals("at Foo3.main(Foo3.java:5)", getLine(doc, 7).trim());
		checkIndentationConsistency(doc, 0);
	}

	/** Test formatting stack trace with mixture of cause and suppressed. */
	public void testFormatSuppressedWithCause() {
		// exception with suppressed and cause
		IDocument doc = consoleDocumentFormatted("Exception in thread \"main\" java.lang.Exception: Main block\n" + "  at Foo3.main(Foo3.java:7)\n"
				+ "  Suppressed: Resource$CloseFailException: Resource ID = 1\n" + "          at Resource.close(Resource.java:26)\n"
				+ "          at Foo3.main(Foo3.java:5)\n" + "Caused by: java.lang.Exception: I did it\n" + "  at Foo3.main(Foo3.java:8)\n");
		assertEquals("Exception in thread \"main\" java.lang.Exception: Main block", getLine(doc, 0));
		assertEquals("at Foo3.main(Foo3.java:7)", getLine(doc, 1).trim());
		assertEquals("Suppressed: Resource$CloseFailException: Resource ID = 1", getLine(doc, 2).trim());
		assertEquals("at Resource.close(Resource.java:26)", getLine(doc, 3).trim());
		assertEquals("at Foo3.main(Foo3.java:5)", getLine(doc, 4).trim());
		assertEquals("Caused by: java.lang.Exception: I did it", getLine(doc, 5).trim());
		assertEquals("at Foo3.main(Foo3.java:8)", getLine(doc, 6).trim());
		checkIndentationConsistency(doc, 0);
		// Additional indentation check. Since cause is linked to primary exception it must be less indented as suppressed stuff.
		assertEquals(getLineIndentation(getLine(doc, 0)), getLineIndentation(getLine(doc, 5)));
		assertEquals(getLineIndentation(getLine(doc, 1)), getLineIndentation(getLine(doc, 6)));
		assertTrue(getLineIndentation(getLine(doc, 3)) > getLineIndentation(getLine(doc, 5)));
		assertTrue(getLineIndentation(getLine(doc, 3)) > getLineIndentation(getLine(doc, 6)));

		// exception with suppressed and cause for the suppressed
		doc = consoleDocumentFormatted("Exception in thread \"main\" java.lang.Exception: Main block\n" + "  at Foo4.main(Foo4.java:6)\n"
				+ "  Suppressed: Resource2$CloseFailException: Resource ID = 1\n" + "          at Resource2.close(Resource2.java:20)\n"
				+ "          at Foo4.main(Foo4.java:5)\n" + "  Caused by: java.lang.Exception: Rats, you caught me\n"
				+ "          at Resource2$CloseFailException.<init>(Resource2.java:45)\n" + "          ... 2 more\n");
		assertEquals("Exception in thread \"main\" java.lang.Exception: Main block", getLine(doc, 0));
		assertEquals("at Foo4.main(Foo4.java:6)", getLine(doc, 1).trim());
		assertEquals("Suppressed: Resource2$CloseFailException: Resource ID = 1", getLine(doc, 2).trim());
		assertEquals("at Resource2.close(Resource2.java:20)", getLine(doc, 3).trim());
		assertEquals("at Foo4.main(Foo4.java:5)", getLine(doc, 4).trim());
		assertEquals("Caused by: java.lang.Exception: Rats, you caught me", getLine(doc, 5).trim());
		assertEquals("at Resource2$CloseFailException.<init>(Resource2.java:45)", getLine(doc, 6).trim());
		assertEquals("... 2 more", getLine(doc, 7).trim());
		checkIndentationConsistency(doc, 0);
		// Additional indentation check. Since cause is linked to suppressed exception it must be greater indented as primary exception stuff.
		assertNotEquals(getLineIndentation(getLine(doc, 0)), getLineIndentation(getLine(doc, 5)));
		assertEquals(getLineIndentation(getLine(doc, 2)), getLineIndentation(getLine(doc, 5)));
		assertNotEquals(getLineIndentation(getLine(doc, 1)), getLineIndentation(getLine(doc, 6)));
		assertEquals(getLineIndentation(getLine(doc, 3)), getLineIndentation(getLine(doc, 6)));
		assertEquals(getLineIndentation(getLine(doc, 4)), getLineIndentation(getLine(doc, 7)));
		assertTrue(getLineIndentation(getLine(doc, 5)) > getLineIndentation(getLine(doc, 0)));
		assertTrue(getLineIndentation(getLine(doc, 6)) > getLineIndentation(getLine(doc, 1)));
	}

	/** Test formatting the rare [CIRCULAR REFERENCE:...] entry. */
	public void testFormatCircular() {
		IDocument doc = consoleDocumentFormatted("Exception in thread \"main\" Stacktrace$BadException\n"
				+ "at Stacktrace.main\n(Stacktrace.java:4)\n" + " Caused by: Stacktrace$BadExceptionCompanion: Stacktrace$BadException\n"
				+ "   at Stacktrace$BadException.<init>(Stacktrace.java:10)\n" + "    ... 1 more\n"
				+ "  [CIRCULAR REFERENCE:Stacktrace$BadException]");
		assertEquals("Exception in thread \"main\" Stacktrace$BadException", getLine(doc, 0));
		assertEquals("at Stacktrace.main(Stacktrace.java:4)", getLine(doc, 1).trim());
		assertEquals("Caused by: Stacktrace$BadExceptionCompanion: Stacktrace$BadException", getLine(doc, 2));
		assertEquals("at Stacktrace$BadException.<init>(Stacktrace.java:10)", getLine(doc, 3).trim());
		assertEquals("... 1 more", getLine(doc, 4).trim());
		assertEquals("[CIRCULAR REFERENCE:Stacktrace$BadException]", getLine(doc, 5).trim());
		checkIndentationConsistency(doc, 0);
	}

	/** Test formatting stack trace from an ant execution. (output mixed with ant prefixes) */
	public void testFormatAnt() {
		IDocument doc = consoleDocumentFormatted("[java] !ENTRY org.eclipse.debug.core 4 120 2005-01-11 03:02:30.321\n"
				+ "     [java] !MESSAGE An exception occurred while dispatching debug events.\n" + "     [java] !STACK 0\n"
				+ "     [java] java.lang.NullPointerException\n" + "     [java] 	at \n"
				+ "org.eclipse.debug.internal.ui.views.console.ProcessConsole.closeStreams\n" + "(ProcessConsole.java:364)\n" + "     [java] 	at \n"
				+ "org.eclipse.debug.internal.ui.views.console.ProcessConsole.handleDebugEvents\n" + "(ProcessConsole.java:438)\n"
				+ "     [java] 	at org.eclipse.debug.core.DebugPlugin$EventNotifier.run\n" + "(DebugPlugin.java:1043)");
		assertEquals("[java] !ENTRY org.eclipse.debug.core 4 120 2005-01-11 03:02:30.321", getLine(doc, 0));
		assertEquals("[java] !MESSAGE An exception occurred while dispatching debug events.", getLine(doc, 1));
		assertEquals("[java] !STACK 0", getLine(doc, 2));
		assertEquals("[java] java.lang.NullPointerException", getLine(doc, 3));
		assertEquals("at org.eclipse.debug.internal.ui.views.console.ProcessConsole.closeStreams(ProcessConsole.java:364)", getLine(doc, 4).replace("[java]", "").trim());
		assertEquals("at org.eclipse.debug.internal.ui.views.console.ProcessConsole.handleDebugEvents(ProcessConsole.java:438)", getLine(doc, 5).replace("[java]", "").trim());
		assertEquals("at org.eclipse.debug.core.DebugPlugin$EventNotifier.run(DebugPlugin.java:1043)", getLine(doc, 6).replace("[java]", "").trim());
		checkIndentationConsistency(doc, 3);
	}

	private IDocument consoleDocumentWithText(String text) throws InterruptedException {
		IDocument document = fConsole.getDocument();
		document.set(text);
		// wait for document being parsed and hyperlinks created
		Job.getJobManager().join(fConsole, null);
		return document;
	}

	private String getLine(IDocument doc, int line) {
		IRegion lineInfo;
		try {
			lineInfo = doc.getLineInformation(line);
			return doc.get(lineInfo.getOffset(), lineInfo.getLength());
		} catch (BadLocationException ex) {
			return null;
		}
	}

	/**
	 * Do some tests on the stack trace indentation. No hardcoded valued just some general assumptions.
	 *
	 * @param doc
	 *            document to test
	 * @param startLine
	 *            first line to check
	 */
	private void checkIndentationConsistency(IDocument doc, int startLine) {
		boolean firstSuppress = true;
		int lastIndent = -1;
		// Remember how the next line's indentation can differ from the previous.
		// -1 -> less indented
		// 0 -> equal
		// 1 -> more indented
		int allowedIndentChange = 1;
		for (int i = startLine, lineCount = doc.getNumberOfLines(); i < lineCount; i++) {
			String line = getLine(doc, i);
			line = line.replaceFirst("^\\[[^\\s\\]]+\\] ", ""); // remove and prefix if any
			if (i != 0) { // first line can be empty
				assertNotEquals("Empty line " + i, "", line);
			}
			assertFalse("Trailing whitespace in line " + i, RIGHT_INDENT.matcher(line).find());

			boolean causedBy = line.trim().startsWith("Caused by: ");
			boolean suppressed = line.trim().startsWith("Suppressed: ");
			if (causedBy || (suppressed && !firstSuppress)) {
				allowedIndentChange = -1;
			}

			int lineIndent = getLineIndentation(line);
			if (allowedIndentChange < 0) {
				assertTrue("Wrong indented line " + i + ": " + lastIndent + " > " + lineIndent, lastIndent > lineIndent);
			} else if (allowedIndentChange == 0) {
				assertEquals("Mixed indentation in line " + i, lastIndent, lineIndent);
			} else if (allowedIndentChange > 0) {
				assertTrue("Wrong indented line " + i + ": " + lastIndent + " < " + lineIndent, lastIndent < lineIndent);
			}
			lastIndent = lineIndent;
			allowedIndentChange = 0;
			if (causedBy || suppressed || i == startLine) {
				allowedIndentChange = 1;
			}
			firstSuppress &= !suppressed;
		}
	}

	private int getLineIndentation(String line) {
		int tabSize = 4;
		String indent = "";
		Matcher m = LEFT_INDENT.matcher(line);
		if (m.find()) {
			indent = m.group();
		}
		int tabCount = indent.length() - indent.replace("\t", "").length();
		return indent.length() + (tabSize - 1) * tabCount;
	}

	/**
	 * Set given text, invoke formatting and wait until finished.
	 *
	 * @param text
	 *            new console text
	 * @return the consoles document
	 */
	private IDocument consoleDocumentFormatted(String text) {
		IDocument document = fConsole.getDocument();
		document.set(text);
		fConsole.format();
		// wait for document being formatted
		TestUtil.waitForJobs(getName(), 30, 1000);
		return document;
	}

	private String[] linkTextsAtPositions(int... offsets) throws BadLocationException {
		IDocument document = fConsole.getDocument();

		List<String> texts = new ArrayList<>(offsets.length);
		List<Position> positions = linkPositions(offsets);
		for (Position pos : positions) {
			String matchText = document.get(pos.getOffset(), pos.getLength());
			texts.add(matchText);
		}
		return texts.toArray(new String[texts.size()]);
	}

	private List<Position> linkPositions(int... offsets) {
		List<Position> filteredPositions = new ArrayList<>(offsets.length);
		for (Position position : allLinkPositions()) {
			for (int offset : offsets) {
				if (offset >= position.getOffset() && offset <= (position.getOffset() + position.getLength())) {
					filteredPositions.add(position);
					break;
				}
			}
		}
		return filteredPositions;
	}

	private Position[] allLinkPositions() {
		try {
			return fConsole.getDocument().getPositions(ConsoleHyperlinkPosition.HYPER_LINK_CATEGORY);
		} catch (BadPositionCategoryException ex) {
			// no hyperlinks
		}
		return new Position[0];
	}

	private String allLinks() {
		return Arrays.toString(allLinkPositions());
	}

	/**
	 * Check if initial content is shown.
	 */
	public void assertInitialContent() {
		assertEquals("Console not loaded with initial content.", ConsoleMessages.JavaStackTraceConsole_0, fConsole.getDocument().get());
	}

	/**
	 * Tries to get the viewer of the currently tested console.
	 *
	 * @return the consoles viewer
	 */
	private TextConsoleViewer getConsolesViewer() {
		TestUtil.waitForJobs(getName(), 100, DEFAULT_TIMEOUT);
		IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		assertNotNull(workbenchWindow);
		IWorkbenchPage activePage = workbenchWindow.getActivePage();
		assertNotNull(activePage);
		JavaStackTraceConsolePage page = null;
		for (IViewReference vref : activePage.getViewReferences()) {
			IViewPart view = vref.getView(false);
			if (view instanceof ConsoleView) {
				ConsoleView consoleView = (ConsoleView) view;
				if (consoleView.getConsole() == fConsole && consoleView.getCurrentPage() instanceof JavaStackTraceConsolePage) {
					page = (JavaStackTraceConsolePage) consoleView.getCurrentPage();
					break;
				}
			}
		}
		assertNotNull(page);
		return page.getViewer();
	}

	/**
	 * Simulate user pressing a key.
	 *
	 * @param widget
	 *            widget to type in
	 * @param c
	 *            character to type
	 */
	private void doKeyStroke(StyledText widget, char c) {
		final Event e = new Event();
		e.character = c;
		widget.notifyListeners(SWT.KeyDown, e);
		widget.notifyListeners(SWT.KeyUp, e);
	}
}
