/*******************************************************************************
 * 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.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.Launch;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.tests.AbstractDebugTest;
import org.eclipse.debug.tests.TestUtil;
import org.eclipse.debug.tests.launching.LaunchConfigurationTests;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.console.ConsoleColorProvider;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleInputStream;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * Tests the ProcessConsole.
 */
public class ProcessConsoleTests extends AbstractDebugTest {
	/**
	 * Number of received log messages with severity error while running a
	 * single test method.
	 */
	private final AtomicInteger loggedErrors = new AtomicInteger(0);

	/** Listener to count error messages in {@link ConsolePlugin} log. */
	private final ILogListener errorLogListener = (status, plugin) -> {
			if (status.matches(IStatus.ERROR)) {
				loggedErrors.incrementAndGet();
			}
	};

	/** Temporary test files created by a test. Will be deleted on teardown. */
	private final ArrayList<File> tmpFiles = new ArrayList<>();

	@Override
	@Before
	public void setUp() throws Exception {
		super.setUp();
		loggedErrors.set(0);
		Platform.addLogListener(errorLogListener);
	}

	@Override
	@After
	public void tearDown() throws Exception {
		Platform.removeLogListener(errorLogListener);
		for (File tmpFile : tmpFiles) {
			tmpFile.delete();
		}
		tmpFiles.clear();

		super.tearDown();

		assertEquals("Test triggered errors.", 0, loggedErrors.get());
	}

	/**
	 * Create a new temporary file for testing. File will be deleted when test
	 * finishes.
	 *
	 * @param filename name of the temporary file
	 * @return the created temporary file
	 * @throws IOException if creating the file failed. Includes file already
	 *             exists.
	 */
	private File createTmpFile(String filename) throws IOException {
		File file = DebugUIPlugin.getDefault().getStateLocation().addTrailingSeparator().append(filename).toFile();
		boolean fileCreated = file.createNewFile();
		assertTrue("Failed to prepare temporary test file.", fileCreated);
		tmpFiles.add(file);
		return file;
	}

	/**
	 * Test if two byte UTF-8 characters get disrupted on there way from process
	 * console to the runtime process.
	 * <p>
	 * This test starts every two byte character on an even byte offset.
	 * </p>
	 */
	@Test
	public void testUTF8InputEven() throws Exception {
		// 5000 characters result in 10000 bytes which should be more than most
		// common buffer sizes.
		processConsoleUTF8Input("", 5000);
	}

	/**
	 * Test if two byte UTF-8 characters get disrupted on there way from process
	 * console to the runtime process.
	 * <p>
	 * This test starts every two byte character on an odd byte offset.
	 * </p>
	 */
	@Test
	public void testUTF8InputOdd() throws Exception {
		// 5000 characters result in 10000 bytes which should be more than most
		// common buffer sizes.
		processConsoleUTF8Input("+", 5000);
	}

	/**
	 * Shared code for the UTF-8 input tests.
	 * <p>
	 * Send some two byte UTF-8 characters through process console user input
	 * stream to mockup process and check if the input got corrupted on its way.
	 * </p>
	 *
	 * @param prefix an arbitrary prefix inserted before the two byte UTF-8
	 *            characters. Used to move the other characters to specific
	 *            offsets e.g. a prefix of one byte will produce an input string
	 *            where every two byte character starts at an odd offset.
	 * @param numTwoByteCharacters number of two byte UTF-8 characters to send
	 *            to process
	 */
	public void processConsoleUTF8Input(String prefix, int numTwoByteCharacters) throws Exception {
		final String input = prefix + String.join("", Collections.nCopies(numTwoByteCharacters, "\u00F8"));
		final MockProcess mockProcess = new MockProcess(input.getBytes(StandardCharsets.UTF_8).length, testTimeout);
		try {
			final ILaunch launch = new Launch(null, ILaunchManager.RUN_MODE, null);
			launch.setAttribute(DebugPlugin.ATTR_CONSOLE_ENCODING, StandardCharsets.UTF_8.toString());
			final IProcess process = DebugPlugin.newProcess(launch, mockProcess, "testUtf8Input");
			@SuppressWarnings("restriction")
			final org.eclipse.debug.internal.ui.views.console.ProcessConsole console = new org.eclipse.debug.internal.ui.views.console.ProcessConsole(process, new ConsoleColorProvider(), StandardCharsets.UTF_8.toString());
			try {
				console.initialize();
				@SuppressWarnings("resource")
				IOConsoleInputStream consoleIn = console.getInputStream();
				consoleIn.appendData(input);
				mockProcess.waitFor(testTimeout, TimeUnit.MILLISECONDS);
			} finally {
				console.destroy();
			}
		} finally {
			mockProcess.destroy();
		}

		final String receivedInput = new String(mockProcess.getReceivedInput(), StandardCharsets.UTF_8);
		assertEquals(input, receivedInput);
	}

	/**
	 * Test if InputReadJob can be canceled.
	 * <p>
	 * Actually tests cancellation for all jobs of
	 * <code>ProcessConsole.class</code> family.
	 * </p>
	 */
	@Test
	public void testInputReadJobCancel() throws Exception {
		final MockProcess mockProcess = new MockProcess(MockProcess.RUN_FOREVER);
		try {
			final IProcess process = mockProcess.toRuntimeProcess("testInputReadJobCancel");
			@SuppressWarnings("restriction")
			final org.eclipse.debug.internal.ui.views.console.ProcessConsole console = new org.eclipse.debug.internal.ui.views.console.ProcessConsole(process, new ConsoleColorProvider());
			try {
				console.initialize();
				@SuppressWarnings("restriction")
				final Class<?> jobFamily = org.eclipse.debug.internal.ui.views.console.ProcessConsole.class;
				assertTrue("Input read job not started.", Job.getJobManager().find(jobFamily).length > 0);
				Job.getJobManager().cancel(jobFamily);
				TestUtil.waitForJobs(name.getMethodName(), 0, 1000);
				assertEquals("Input read job not canceled.", 0, Job.getJobManager().find(jobFamily).length);
			} finally {
				console.destroy();
			}
		} finally {
			mockProcess.destroy();
		}
	}

	/**
	 * Test console finished notification with standard process console.
	 */
	@Test
	public void testProcessTerminationNotification() throws Exception {
		TestUtil.log(IStatus.INFO, name.getMethodName(), "Process terminates after Console is initialized.");
		processTerminationTest(null, false);
		TestUtil.log(IStatus.INFO, name.getMethodName(), "Process terminates before Console is initialized.");
		processTerminationTest(null, true);
	}

	/**
	 * Test console finished notification if process standard input is feed from
	 * file.
	 */
	@Test
	public void testProcessTerminationNotificationWithInputFile() throws Exception {
		File inFile = DebugUIPlugin.getDefault().getStateLocation().addTrailingSeparator().append("testStdin.txt").toFile();
		boolean fileCreated = inFile.createNewFile();
		assertTrue("Failed to prepare input file.", fileCreated);
		try {
			ILaunchConfigurationType launchType = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(LaunchConfigurationTests.ID_TEST_LAUNCH_TYPE);
			ILaunchConfigurationWorkingCopy launchConfiguration = launchType.newInstance(null, "testProcessTerminationNotificationWithInputFromFile");
			launchConfiguration.setAttribute(IDebugUIConstants.ATTR_CAPTURE_STDIN_FILE, inFile.getAbsolutePath());
			TestUtil.log(IStatus.INFO, name.getMethodName(), "Process terminates after Console is initialized.");
			processTerminationTest(launchConfiguration, false);
			TestUtil.log(IStatus.INFO, name.getMethodName(), "Process terminates before Console is initialized.");
			processTerminationTest(launchConfiguration, true);
		} finally {
			inFile.delete();
		}
	}

	/**
	 * The shared code to test console finished notification.
	 *
	 * @param launchConfig <code>null</code> or configured with stdin file.
	 * @param terminateBeforeConsoleInitialization if <code>true</code> the
	 *            tested process is terminated before the ProcessConsole can
	 *            perform its initialization. If <code>false</code> the process
	 *            is guaranteed to run until the ProcessConsole was initialized.
	 */
	public void processTerminationTest(ILaunchConfiguration launchConfig, boolean terminateBeforeConsoleInitialization) throws Exception {
		final AtomicBoolean terminationSignaled = new AtomicBoolean(false);
		final Process mockProcess = new MockProcess(null, null, terminateBeforeConsoleInitialization ? 0 : -1);
		final IProcess process = DebugPlugin.newProcess(new Launch(launchConfig, ILaunchManager.RUN_MODE, null), mockProcess, "testProcessTerminationNotification");
		@SuppressWarnings("restriction")
		final org.eclipse.debug.internal.ui.views.console.ProcessConsole console = new org.eclipse.debug.internal.ui.views.console.ProcessConsole(process, new ConsoleColorProvider());
		console.addPropertyChangeListener(event -> {
				if (event.getSource() == console && IConsoleConstants.P_CONSOLE_OUTPUT_COMPLETE.equals(event.getProperty())) {
					terminationSignaled.set(true);
				}
		});
		final IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();
		try {
			consoleManager.addConsoles(new IConsole[] { console });
			if (mockProcess.isAlive()) {
				mockProcess.destroy();
			}
			TestUtil.waitForJobs(name.getMethodName(), 50, 10000);
			assertTrue("No console complete notification received.", terminationSignaled.get());
		} finally {
			consoleManager.removeConsoles(new IConsole[] { console });
			TestUtil.waitForJobs(name.getMethodName(), 0, 10000);
		}
	}

	/**
	 * Test simple redirect of console output into file.
	 */
	@Test
	public void testRedirectOutputToFile() throws Exception {
		final String testContent = "Hello World!";
		final File outFile = createTmpFile("test.out");
		Map<String, Object> launchConfigAttributes = new HashMap<>();
		launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_FILE, outFile.getCanonicalPath());
		launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_CONSOLE, true);
		doConsoleOutputTest(testContent.getBytes(), launchConfigAttributes);
		assertArrayEquals("Wrong content redirected to file.", testContent.getBytes(), Files.readAllBytes(outFile.toPath()));
	}

	/**
	 * Test appending of console output into existing file.
	 */
	@Test
	public void testAppendOutputToFile() throws Exception {
		final String testContent = "Hello World!";
		final File outFile = createTmpFile("test.out");
		Map<String, Object> launchConfigAttributes = new HashMap<>();
		launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_FILE, outFile.getCanonicalPath());
		launchConfigAttributes.put(IDebugUIConstants.ATTR_APPEND_TO_FILE, true);
		launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_CONSOLE, true);
		doConsoleOutputTest(testContent.getBytes(), launchConfigAttributes);
		assertArrayEquals("Wrong content redirected to file.", testContent.getBytes(), Files.readAllBytes(outFile.toPath()));

		String appendedContent = "append";
		doConsoleOutputTest(appendedContent.getBytes(), launchConfigAttributes);
		assertArrayEquals("Wrong content redirected to file.", (testContent + appendedContent).getBytes(), Files.readAllBytes(outFile.toPath()));
	}

	/**
	 * Test output redirect with a filename containing regular expression
	 * specific special characters.
	 * <p>
	 * Test a filename with special characters which is still a valid regular
	 * expression and a filename whose name is an invalid regular expression.
	 */
	@Test
	public void testBug333239_regexSpecialCharactersInOutputFilename() throws Exception {
		final String testContent = "1.\n2.\n3.\n";
		File outFile = createTmpFile("test.[out]");
		Map<String, Object> launchConfigAttributes = new HashMap<>();
		launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_FILE, outFile.getCanonicalPath());
		launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_CONSOLE, false);
		IOConsole console = doConsoleOutputTest(testContent.getBytes(), launchConfigAttributes);
		assertArrayEquals("Wrong content redirected to file.", testContent.getBytes(), Files.readAllBytes(outFile.toPath()));
		assertEquals("Output in console.", 2, console.getDocument().getNumberOfLines());

		outFile = createTmpFile("exhaustive[128-32].out");
		launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_FILE, outFile.getCanonicalPath());
		console = doConsoleOutputTest(testContent.getBytes(), launchConfigAttributes);
		assertArrayEquals("Wrong content redirected to file.", testContent.getBytes(), Files.readAllBytes(outFile.toPath()));
		assertEquals("Output in console.", 2, console.getDocument().getNumberOfLines());

		outFile = createTmpFile("ug(ly.out");
		launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_FILE, outFile.getCanonicalPath());
		console = doConsoleOutputTest(testContent.getBytes(), launchConfigAttributes);
		assertArrayEquals("Wrong content redirected to file.", testContent.getBytes(), Files.readAllBytes(outFile.toPath()));
		assertEquals("Output in console.", 2, console.getDocument().getNumberOfLines());
	}

	/**
	 * Shared test code for tests who want to write and verify content to
	 * console. Method will open a console for a mockup process, output the
	 * given content, terminate the process and close the console. If content is
	 * expected to be found in console it will be verified. If output is
	 * redirected to file the file path which should be printed to console is
	 * checked.
	 *
	 * @param testContent content to output in console
	 * @param launchConfigAttributes optional launch configuration attributes to
	 *            specify behavior
	 * @return the console object after it has finished
	 */
	private IOConsole doConsoleOutputTest(byte[] testContent, Map<String, Object> launchConfigAttributes) throws Exception {
		final MockProcess mockProcess = new MockProcess(new ByteArrayInputStream(testContent), null, 0);
		final IProcess process = mockProcess.toRuntimeProcess("Output Redirect", launchConfigAttributes);
		final String encoding = launchConfigAttributes != null ? (String) launchConfigAttributes.get(DebugPlugin.ATTR_CONSOLE_ENCODING) : null;
		final AtomicBoolean consoleFinished = new AtomicBoolean(false);
		@SuppressWarnings("restriction")
		final org.eclipse.debug.internal.ui.views.console.ProcessConsole console = new org.eclipse.debug.internal.ui.views.console.ProcessConsole(process, new ConsoleColorProvider(), encoding);
		console.addPropertyChangeListener((PropertyChangeEvent event) -> {
			if (event.getSource() == console && IConsoleConstants.P_CONSOLE_OUTPUT_COMPLETE.equals(event.getProperty())) {
				consoleFinished.set(true);
			}
		});
		final IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();
		try {
			consoleManager.addConsoles(new IConsole[] { console });
			waitWhile(c -> !consoleFinished.get(), testTimeout, c -> "Console did not finished.");

			Object value = launchConfigAttributes != null ? launchConfigAttributes.get(IDebugUIConstants.ATTR_CAPTURE_IN_FILE) : null;
			final File outFile = value != null ? new File((String) value) : null;
			value = launchConfigAttributes != null ? launchConfigAttributes.get(IDebugUIConstants.ATTR_CAPTURE_IN_CONSOLE) : null;
			final boolean checkOutput = value != null ? (boolean) value : true;
			final IDocument doc = console.getDocument();

			if (outFile != null) {
				@SuppressWarnings("restriction")
				String expectedPathMsg = MessageFormat.format(org.eclipse.debug.internal.ui.views.console.ConsoleMessages.ProcessConsole_1, new Object[] {
						outFile.getAbsolutePath() });
				assertEquals("No or wrong output of redirect file path in console.", expectedPathMsg, doc.get(doc.getLineOffset(0), doc.getLineLength(0)));
				assertEquals("Expected redirect file path to be linked.", 1, console.getHyperlinks().length);
			}
			if (checkOutput) {
				assertEquals("Output not found in console.", new String(testContent), doc.get(doc.getLineOffset(1), doc.getLineLength(1)));
			}
			return console;
		} finally {
			if (!process.isTerminated()) {
				process.terminate();
			}
			consoleManager.removeConsoles(new IConsole[] { console });
			TestUtil.waitForJobs(name.getMethodName(), 0, 1000);
		}
	}

	/**
	 * Simulate the common case of a process which constantly produce output.
	 * This should cover the situation that a process produce output before
	 * ProcessConsole is initialized and more output after console is ready.
	 */
	@Test
	public void testOutput() throws Exception {
		String[] lines = new String[] {
				"'Native' process started.",
				"'Eclipse' process started. Stream proxying started.",
				"Console created.", "Console initialized.",
				"Stopping mock process.", };
		String consoleEncoding = StandardCharsets.UTF_8.name();
		try (PipedOutputStream procOut = new PipedOutputStream(); PrintStream sysout = new PrintStream(procOut, true, consoleEncoding)) {
			@SuppressWarnings("resource")
			final MockProcess mockProcess = new MockProcess(new PipedInputStream(procOut), null, MockProcess.RUN_FOREVER);
			sysout.println(lines[0]);
			try {
				Map<String, Object> launchConfigAttributes = new HashMap<>();
				launchConfigAttributes.put(DebugPlugin.ATTR_CONSOLE_ENCODING, consoleEncoding);
				final IProcess process = mockProcess.toRuntimeProcess("simpleOutput", launchConfigAttributes);
				sysout.println(lines[1]);
				@SuppressWarnings("restriction")
				final org.eclipse.debug.internal.ui.views.console.ProcessConsole console = new org.eclipse.debug.internal.ui.views.console.ProcessConsole(process, new ConsoleColorProvider(), consoleEncoding);
				sysout.println(lines[2]);
				try {
					console.initialize();
					sysout.println(lines[3]);
					sysout.println(lines[4]);
					mockProcess.destroy();
					sysout.close();
					TestUtil.processUIEvents(200);

					for (int i = 0; i < lines.length; i++) {
						IRegion lineInfo = console.getDocument().getLineInformation(i);
						String line = console.getDocument().get(lineInfo.getOffset(), lineInfo.getLength());
						assertEquals("Wrong content in line " + i, lines[i], line);
					}
				} finally {
					console.destroy();
				}
			} finally {
				mockProcess.destroy();
			}
		}
	}

	/**
	 * Test a process which produces binary output and a launch which redirects
	 * output to file. The process output must not be changed in any way due to
	 * the redirection. See bug 558463.
	 */
	@Test
	public void testBinaryOutputToFile() throws Exception {
		byte[] output = new byte[] { (byte) 0xac };
		String consoleEncoding = StandardCharsets.UTF_8.name();

		final File outFile = createTmpFile("testoutput.bin");
		final MockProcess mockProcess = new MockProcess(new ByteArrayInputStream(output), null, MockProcess.RUN_FOREVER);
		try {
			Map<String, Object> launchConfigAttributes = new HashMap<>();
			launchConfigAttributes.put(DebugPlugin.ATTR_CONSOLE_ENCODING, consoleEncoding);
			launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_FILE, outFile.getCanonicalPath());
			launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_CONSOLE, false);
			final IProcess process = mockProcess.toRuntimeProcess("redirectBinaryOutput", launchConfigAttributes);
			@SuppressWarnings("restriction")
			final org.eclipse.debug.internal.ui.views.console.ProcessConsole console = new org.eclipse.debug.internal.ui.views.console.ProcessConsole(process, new ConsoleColorProvider(), consoleEncoding);
			try {
				console.initialize();
				mockProcess.waitFor(100, TimeUnit.MILLISECONDS);
				mockProcess.destroy();
			} finally {
				console.destroy();
			}
		} finally {
			mockProcess.destroy();
		}

		byte[] receivedOutput = Files.readAllBytes(outFile.toPath());
		assertArrayEquals(output, receivedOutput);
	}

	/**
	 * Test a process which reads binary input from a file through Eclipse
	 * console. The input must not be changed in any way due to the redirection.
	 * See bug 558463.
	 */
	@Test
	public void testBinaryInputFromFile() throws Exception {
		byte[] input = new byte[] { (byte) 0xac };
		String consoleEncoding = StandardCharsets.UTF_8.name();

		final File inFile = createTmpFile("testinput.bin");
		Files.write(inFile.toPath(), input);
		final MockProcess mockProcess = new MockProcess(input.length, testTimeout);
		try {
			Map<String, Object> launchConfigAttributes = new HashMap<>();
			launchConfigAttributes.put(DebugPlugin.ATTR_CONSOLE_ENCODING, consoleEncoding);
			launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_STDIN_FILE, inFile.getCanonicalPath());
			launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_CONSOLE, false);
			final IProcess process = mockProcess.toRuntimeProcess("redirectBinaryInput", launchConfigAttributes);
			@SuppressWarnings("restriction")
			final org.eclipse.debug.internal.ui.views.console.ProcessConsole console = new org.eclipse.debug.internal.ui.views.console.ProcessConsole(process, new ConsoleColorProvider(), consoleEncoding);
			try {
				console.initialize();
				mockProcess.waitFor(testTimeout, TimeUnit.MILLISECONDS);
			} finally {
				console.destroy();
			}
		} finally {
			mockProcess.destroy();
		}

		byte[] receivedInput = mockProcess.getReceivedInput();
		assertArrayEquals(input, receivedInput);
	}
}
