/*******************************************************************************
 * Copyright (c) 2004, 2014 IBM Corporation 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:
 *	IBM Corporation - initial API and implementation
 *	Martin Oberhuber (Wind River) - [232426] createSymLink() method
 *	Martin Oberhuber (Wind River) - [335864] ResourceAttributeTest fails on Win7
 *	Sergey Prigogin (Google) - [440283] Modify symlink tests to run on Windows with or without administrator privileges
 *******************************************************************************/
package org.eclipse.core.tests.harness;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.osgi.framework.Version;

/**
 * @since 3.1
 */
public class CoreTest extends TestCase {
	private static Boolean canCreateSymLinks;

	/** counter for generating unique random file system locations */
	protected static int nextLocationCounter = 0;

	// plug-in identified for the core.tests.harness plug-in.
	public static final String PI_HARNESS = "org.eclipse.core.tests.harness";

	public static void debug(String message) {
		String id = "org.eclipse.core.tests.harness/debug";
		String option = Platform.getDebugOption(id);
		if (Boolean.TRUE.toString().equalsIgnoreCase(option)) {
			System.out.println(message);
		}
	}

	/**
	 * Fails the test due to the given throwable.
	 */
	public static void fail(String message, Throwable e) {
		// If the exception is a CoreException with a multistatus
		// then print out the multistatus so we can see all the info.
		if (e instanceof CoreException) {
			IStatus status = ((CoreException) e).getStatus();
			//if the status does not have an exception, print the stack for this one
			if (status.getException() == null) {
				e.printStackTrace();
			}
			write(status, 0);
		} else {
			e.printStackTrace();
		}
		AssertionFailedError assertFail = new AssertionFailedError(message + ": " + e);
		assertFail.initCause(e);
		throw assertFail;
	}

	private static void indent(OutputStream output, int indent) {
		for (int i = 0; i < indent; i++) {
			try {
				output.write("\t".getBytes());
			} catch (IOException e) {
				// ignore
			}
		}
	}

	public static void log(String pluginID, IStatus status) {
		Platform.getLog(Platform.getBundle(pluginID)).log(status);
	}

	public static void log(String pluginID, Throwable e) {
		log(pluginID, new Status(IStatus.ERROR, pluginID, IStatus.ERROR, "Error", e)); //$NON-NLS-1$
	}

	private static void write(IStatus status, int indent) {
		PrintStream output = System.out;
		indent(output, indent);
		output.println("Severity: " + status.getSeverity());

		indent(output, indent);
		output.println("Plugin ID: " + status.getPlugin());

		indent(output, indent);
		output.println("Code: " + status.getCode());

		indent(output, indent);
		output.println("Message: " + status.getMessage());

		if (status.getException() != null) {
			indent(output, indent);
			output.print("Exception: ");
			status.getException().printStackTrace(output);
		}

		if (status.isMultiStatus()) {
			IStatus[] children = status.getChildren();
			for (IStatus element : children) {
				write(element, indent + 1);
			}
		}
	}

	public CoreTest() {
		super();
	}

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

	/**
	 * Asserts that a stream closes successfully. Null streams
	 * are ignored, but failure to close the stream is reported as
	 * an assertion failure.
	 * @since 3.2
	 */
	protected void assertClose(InputStream stream) {
		if (stream == null) {
			return;
		}
		try {
			stream.close();
		} catch (IOException e) {
			fail("Failed close in assertClose", e);
		}
	}

	/**
	 * Asserts that a stream closes successfully. Null streams
	 * are ignored, but failure to close the stream is reported as
	 * an assertion failure.
	 * @since 3.2
	 */
	protected void assertClose(OutputStream stream) {
		if (stream == null) {
			return;
		}
		try {
			stream.close();
		} catch (IOException e) {
			fail("Failed close in assertClose", e);
		}
	}

	protected void assertEquals(String message, Object[] expected, Object[] actual) {
		if (expected == null && actual == null) {
			return;
		}
		if (expected == null || actual == null) {
			fail(message);
		}
		if (expected.length != actual.length) {
			fail(message);
		}
		for (int i = 0; i < expected.length; i++) {
			assertEquals(message, expected[i], actual[i]);
		}
	}

	protected void assertEquals(String message, Object[] expected, Object[] actual, boolean orderImportant) {
		// if the order in the array must match exactly, then call the other method
		if (orderImportant) {
			assertEquals(message, expected, actual);
			return;
		}
		// otherwise use this method and check that the arrays are equal in any order
		if (expected == null && actual == null) {
			return;
		}
		if (expected == actual) {
			return;
		}
		if (expected == null || actual == null) {
			assertTrue(message + ".1", false);
		}
		if (expected.length != actual.length) {
			assertTrue(message + ".2", false);
		}
		boolean[] found = new boolean[expected.length];
		for (Object element : expected) {
			for (int j = 0; j < expected.length; j++) {
				if (!found[j] && element.equals(actual[j])) {
					found[j] = true;
				}
			}
		}
		for (int i = 0; i < found.length; i++) {
			if (!found[i]) {
				assertTrue(message + ".3." + i, false);
			}
		}
	}

	/**
	 * Create the given file in the file system.
	 */
	public void createFileInFileSystem(File file, InputStream contents) throws IOException {
		file.getParentFile().mkdirs();
		FileOutputStream output = new FileOutputStream(file);
		transferData(contents, output);
	}

	/**
	 * Creates a symbolic link.
	 * Should only be called on platforms where symbolic links can actually
	 * be created, i.e. an "ln" command is available.
	 * @param basedir folder in which the symbolic link should be created
	 * @param linkName name of the symbolic link
	 * @param linkTarget target to which the symbolic link should point
	 * @param isDir <code>true</code> if the link should point to a folder
	 * @throws AssertionFailedError if creation of the symbolic link failed
	 */
	protected void createSymLink(File basedir, String linkName, String linkTarget, boolean isDir) {
		// Deliberately use an empty environment to make the test reproducible.
		String[] envp = {};
		try {
			Process p;
			if (isWindowsVistaOrHigher()) {
				if (isDir) {
					String[] cmd = {"cmd", "/c", "mklink", "/d", linkName, linkTarget};
					p = Runtime.getRuntime().exec(cmd, envp, basedir);
				} else {
					String[] cmd = {"cmd", "/c", "mklink", linkName, linkTarget};
					p = Runtime.getRuntime().exec(cmd, envp, basedir);
				}
			} else {
				String[] cmd = {"ln", "-s", linkTarget, linkName};
				p = Runtime.getRuntime().exec(cmd, envp, basedir);
			}
			int exitcode = p.waitFor();
			if (exitcode != 0) {
				String result = new BufferedReader(new InputStreamReader(p.getErrorStream())).readLine();
				assertEquals("createSymLink: " + result + ", exitcode", 0, exitcode);
			}
		} catch (IOException | InterruptedException e) {
			fail("createSymLink", e);
		}
	}

	/**
	 * Checks whether it is possible for a test to create a symbolic link.
	 *
	 * @return <code>true</code> if symbolic links can be created by a test
	 */
	protected boolean canCreateSymLinks() {
		if (canCreateSymLinks == null) {
			if (isWindowsVistaOrHigher()) {
				// Creation of a symbolic link on Windows requires administrator privileges,
				// so it may or may not be possible.
				IPath tempDir = getTempDir();
				String linkName = FileSystemHelper.getRandomLocation(tempDir).lastSegment();
				try {
					// Try to create a symlink.
					createSymLink(tempDir.toFile(), linkName, "testTarget", false);
					// Clean up if the link was created.
					new File(tempDir.toFile(), linkName).delete();
					canCreateSymLinks = Boolean.TRUE;
				} catch (AssertionFailedError e) {
					// This exception indicates that creation of the symlink failed.
					canCreateSymLinks = Boolean.FALSE;
				}
			} else {
				canCreateSymLinks = Boolean.TRUE;
			}
		}
		return canCreateSymLinks.booleanValue();
	}

	protected void ensureDoesNotExistInFileSystem(java.io.File file) {
		FileSystemHelper.clear(file);
	}

	public InputStream getContents(java.io.File target, String errorCode) {
		try {
			return new FileInputStream(target);
		} catch (IOException e) {
			fail(errorCode, e);
		}
		return null; // never happens
	}

	/**
	 * Return an input stream with some the specified text to use
	 * as contents for a file resource.
	 */
	public InputStream getContents(String text) {
		return new ByteArrayInputStream(text.getBytes());
	}

	public IProgressMonitor getMonitor() {
		return new FussyProgressMonitor();
	}

	/**
	 * Return an input stream with some random text to use
	 * as contents for a file resource.
	 */
	public InputStream getRandomContents() {
		return new ByteArrayInputStream(getRandomString().getBytes());
	}

	/**
	 * Returns a unique location on disk.  It is guaranteed that no file currently
	 * exists at that location.  The returned location will be unique with respect
	 * to all other locations generated by this method in the current session.
	 * If the caller creates a folder or file at this location, they are responsible for
	 * deleting it when finished.
	 */
	public IPath getRandomLocation() {
		return FileSystemHelper.getRandomLocation(getTempDir());
	}

	/**
	 * Return String with some random text to use
	 * as contents for a file resource.
	 */
	public String getRandomString() {
		switch ((int) Math.round(Math.random() * 10)) {
			case 0 :
				return "este e' o meu conteudo (portuguese)";
			case 1 :
				return "ho ho ho";
			case 2 :
				return "I'll be back";
			case 3 :
				return "don't worry, be happy";
			case 4 :
				return "there is no imagination for more sentences";
			case 5 :
				return "Alexandre Bilodeau, Canada's first home gold. 14/02/2010";
			case 6 :
				return "foo";
			case 7 :
				return "bar";
			case 8 :
				return "foobar";
			case 9 :
				return "case 9";
			default :
				return "these are my contents";
		}
	}

	public IPath getTempDir() {
		return FileSystemHelper.getTempDir();
	}

	public String getUniqueString() {
		return System.currentTimeMillis() + "-" + Math.random();
	}

	protected static boolean isWindowsMinVersion(int major, int minor, int micro) {
		if (Platform.getOS().equals(Platform.OS_WIN32)) {
			try {
				Version v = Version.parseVersion(System.getProperty("org.osgi.framework.os.version")); //$NON-NLS-1$
				System.out.println("Windows version: " + Version.parseVersion(System.getProperty("org.osgi.framework.os.version")));
				return v.compareTo(new Version(major, minor, micro)) >= 0;
			} catch (IllegalArgumentException e) {
				/* drop down to returning false */
			}

		}
		return false;
	}

	/**
	 * Test if running on Windows Vista or higher.
	 * @return <code>true</code> if running on Windows Vista or higher.
	 */
	protected static boolean isWindowsVistaOrHigher() {
		return isWindowsMinVersion(6, 0, 0);
	}

	/**
	 * Copy the data from the input stream to the output stream.
	 * Close both streams when finished.
	 */
	public void transferData(InputStream input, OutputStream output) {
		try {
			try {
				int c = 0;
				while ((c = input.read()) != -1) {
					output.write(c);
				}
			} finally {
				input.close();
				output.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
			assertTrue(e.toString(), false);
		}
	}

	/**
	 * Copy the data from the input stream to the output stream.
	 * Do not close either of the streams.
	 */
	public void transferDataWithoutClose(InputStream input, OutputStream output) {
		try {
			int c = 0;
			while ((c = input.read()) != -1) {
				output.write(c);
			}
		} catch (IOException e) {
			e.printStackTrace();
			assertTrue(e.toString(), false);
		}
	}

	public static void assertSame(String message, int expected, int actual) {
		if (expected == actual) {
			return;
		}
		failNotSame(message, expected, actual);
	}

	public static void failNotSame(String message, int expected, int actual) {
		StringBuilder formatted = new StringBuilder();
		if (message != null) {
			formatted.append(message).append(' ');
		}
		formatted.append("expected same:<").append(expected).append("> was not:<").append(actual).append(">");
		fail(String.valueOf(formatted));
	}

	public static void assertSame(String message, boolean expected, boolean actual) {
		if (expected == actual) {
			return;
		}
		failNotSame(message, expected, actual);
	}

	public static void failNotSame(String message, boolean expected, boolean actual) {
		StringBuilder formatted = new StringBuilder();
		if (message != null) {
			formatted.append(message).append(' ');
		}
		formatted.append("expected same:<").append(expected).append("> was not:<").append(actual).append(">");
		fail(String.valueOf(formatted));
	}

	public static void assertSame(String message, float expected, float actual) {
		if (expected == actual) {
			return;
		}
		failNotSame(message, expected, actual);
	}

	public static void failNotSame(String message, float expected, float actual) {
		StringBuilder formatted = new StringBuilder();
		if (message != null) {
			formatted.append(message).append(' ');
		}
		formatted.append("expected same:<").append(expected).append("> was not:<").append(actual).append(">");
		fail(String.valueOf(formatted));
	}

	public static void assertSame(String message, double expected, double actual) {
		if (expected == actual) {
			return;
		}
		failNotSame(message, expected, actual);
	}

	public static void failNotSame(String message, double expected, double actual) {
		StringBuilder formatted = new StringBuilder();
		if (message != null) {
			formatted.append(message).append(' ');
		}
		formatted.append("expected same:<").append(expected).append("> was not:<").append(actual).append(">");
		fail(String.valueOf(formatted));
	}

	public static void assertSame(String message, long expected, long actual) {
		if (expected == actual) {
			return;
		}
		failNotSame(message, expected, actual);
	}

	public static void failNotSame(String message, long expected, long actual) {
		StringBuilder formatted = new StringBuilder();
		if (message != null) {
			formatted.append(message).append(' ');
		}
		formatted.append("expected same:<").append(expected).append("> was not:<").append(actual).append(">");
		fail(String.valueOf(formatted));
	}
}
