blob: 57a6b4823c336b46f6c8eaeef9c557ae54638a06 [file] [log] [blame]
/*******************************************************************************
* 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 e) {
fail("createSymLink", e);
} catch (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));
}
}