/*******************************************************************************
 * Copyright (c) 2004, 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.core.tests.session;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import junit.framework.Test;
import junit.framework.TestResult;
import junit.framework.TestSuite;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.tests.harness.CoreTest;

/**
 * This class is responsible for launching JUnit tests on a separate Eclipse session and collect
 * the tests results sent back through a socket . 
 */
public class SessionTestRunner {

	class Result {
		final static int ERROR = 2;
		final static int FAILURE = 1;
		final static int SUCCESS = 0;

		String message;

		String stackTrace;
		Test test;
		int type;

		public Result(Test test) {
			this.test = test;
		}
	}

	/**
	 * Collectors can be used a single time only.
	 */
	class ResultCollector implements Runnable {
		private boolean finished;
		private Result newResult;
		private Map results = new HashMap();
		ServerSocket serverSocket;
		private boolean shouldRun = true;
		private StringBuffer stack;
		private TestResult testResult;
		// tests completed during this session
		private int testsRun;

		ResultCollector(Test test, TestResult testResult) throws IOException {
			serverSocket = new ServerSocket(0);
			this.testResult = testResult;
			initResults(test);
		}

		public int getPort() {
			return serverSocket.getLocalPort();
		}

		public int getTestsRun() {
			return testsRun;
		}

		private void initResults(Test test) {
			if (test instanceof TestSuite) {
				for (Enumeration e = ((TestSuite) test).tests(); e.hasMoreElements();)
					initResults((Test) e.nextElement());
				return;
			}
			results.put(test.toString(), new Result(test));
		}

		public synchronized boolean isFinished() {
			return finished;
		}

		private synchronized void markAsFinished() {
			finished = true;
			notifyAll();
		}

		private String parseTestId(String message) {
			if (message.length() == 0 || message.charAt(0) != '%')
				return null;
			int firstComma = message.indexOf(',');
			if (firstComma == -1)
				return null;
			int secondComma = message.indexOf(',', firstComma + 1);
			if (secondComma == -1)
				secondComma = message.length();
			return message.substring(firstComma + 1, secondComma);
		}

		private void processAvailableMessages(BufferedReader messageReader) throws IOException {
			while (messageReader.ready()) {
				String message = messageReader.readLine();
				processMessage(message);
			}
		}

		private void processMessage(String message) {
			if (message.startsWith("%TESTS")) {
				String testId = parseTestId(message);
				if (!results.containsKey(testId))
					throw new IllegalStateException("Unknown test id: " + testId);
				newResult = (Result) results.get(testId);
				testResult.startTest(newResult.test);
				return;
			}
			if (message.startsWith("%TESTE")) {
				if (newResult.type == Result.FAILURE)
					testResult.addFailure(newResult.test, new RemoteAssertionFailedError(newResult.message, newResult.stackTrace));
				else if (newResult.type == Result.ERROR)
					testResult.addError(newResult.test, new RemoteTestException(newResult.message, newResult.stackTrace));
				testResult.endTest(newResult.test);
				testsRun++;
				newResult = null;
				return;
			}
			if (message.startsWith("%ERROR")) {
				newResult.type = Result.ERROR;
				newResult.message = "";
				return;
			}
			if (message.startsWith("%FAILED")) {
				newResult.type = Result.FAILURE;
				newResult.message = "";
				return;
			}
			if (message.startsWith("%TRACES")) {
				// just create the string buffer that will hold all the frames of the stack trace
				stack = new StringBuffer();
				return;
			}
			if (message.startsWith("%TRACEE")) {
				// stack trace fully read - fill the slot in the result object and reset the string buffer
				newResult.stackTrace = stack.toString();
				stack = null;
				return;
			}
			if (message.startsWith("%"))
				// ignore any other messages
				return;
			if (stack != null) {
				// build the stack trace line by line
				stack.append(message);
				stack.append(System.getProperty("line.separator"));
				return;
			}
		}

		public void run() {
			Socket connection = null;
			try {
				// someone asked us to stop before we could do anything
				if (!shouldRun())
					return;
				try {
					connection = serverSocket.accept();
				} catch (SocketException se) {
					if (!shouldRun())
						// we have been finished without ever getting any connections
						// no need to throw exception
						return;
					// something else stopped us
					throw se;
				}
				BufferedReader messageReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
				try {
					// main loop
					while (true) {
						synchronized (this) {
							processAvailableMessages(messageReader);
							if (!shouldRun())
								return;
							this.wait(150);
						}
					}
				} catch (InterruptedException e) {
					// not expected
				}
			} catch (IOException e) {
				CoreTest.log(CoreTest.PI_HARNESS, e);
			} finally {
				// remember we are already finished
				markAsFinished();
				// cleanup
				try {
					if (connection != null && !connection.isClosed())
						connection.close();
				} catch (IOException e) {
					CoreTest.log(CoreTest.PI_HARNESS, e);
				}
				try {
					if (serverSocket != null && !serverSocket.isClosed())
						serverSocket.close();
				} catch (IOException e) {
					CoreTest.log(CoreTest.PI_HARNESS, e);
				}
			}
		}

		private synchronized boolean shouldRun() {
			return shouldRun;
		}

		/*
		 * Politely asks the collector thread to stop and wait until it is finished.
		 */
		public void shutdown() {
			// ask the collector to stop
			synchronized (this) {
				if (isFinished())
					return;
				shouldRun = false;
				try {
					serverSocket.close();
				} catch (IOException e) {
					CoreTest.log(CoreTest.PI_HARNESS, e);
				}
				notifyAll();
			}
			// wait until the collector is done
			synchronized (this) {
				while (!isFinished())
					try {
						wait(100);
					} catch (InterruptedException e) {
						// we don't care
					}
			}
		}

	}

	/**
	 * Runs the setup. Returns a status object indicating the outcome of the operation.
	 *   
	 * @return a status object indicating the outcome 
	 */
	private IStatus launch(Setup setup) {
		Assert.isNotNull(setup.getEclipseArgument(Setup.APPLICATION), "test application is not defined");
		Assert.isNotNull(setup.getEclipseArgument("testpluginname"), "test plug-in id not defined");
		Assert.isTrue(setup.getEclipseArgument("classname") != null ^ setup.getEclipseArgument("test") != null, "either a test suite or a test case must be provided");
		// to prevent changes in the protocol from breaking us, 
		// force the version we know we can work with 
		setup.setEclipseArgument("version", "3");
		IStatus outcome = Status.OK_STATUS;
		try {
			int returnCode = setup.run();
			if (returnCode == 23) {
				// asked to restart; for now just do this once
				returnCode = setup.run();
			}
			if (returnCode != 0)
				outcome = new Status(IStatus.WARNING, Platform.PI_RUNTIME, returnCode, "Process returned non-zero code: " + returnCode + "\n\tCommand: " + setup, null);
		} catch (Exception e) {
			outcome = new Status(IStatus.ERROR, Platform.PI_RUNTIME, -1, "Error running process\n\tCommand: " + setup, e);
		}
		return outcome;
	}

	/**
	 * Runs the test described  in a separate session.
	 */
	public final void run(Test test, TestResult result, Setup setup, boolean crashTest) {
		ResultCollector collector = null;
		try {
			collector = new ResultCollector(test, result);
		} catch (IOException e) {
			result.addError(test, e);
			return;
		}
		setup.setEclipseArgument("port", Integer.toString(collector.getPort()));
		new Thread(collector, "Test result collector").start();
		IStatus status = launch(setup);
		collector.shutdown();
		// ensure the session ran without any errors
		if (!status.isOK()) {
			CoreTest.log(CoreTest.PI_HARNESS, status);
			if (status.getSeverity() == IStatus.ERROR) {
				result.addError(test, new CoreException(status));
				return;
			}
		}
		if (collector.getTestsRun() == 0) {
			if (crashTest)
				// explicitly end test since process crashed before test could finish
				result.endTest(test);
			else
				result.addError(test, new Exception("Test did not run: " + test.toString()));
		} else if (crashTest)
			result.addError(test, new Exception("Should have caused crash"));
	}
}
