/*******************************************************************************
* Copyright (c) 2016 Zend Technologies 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:
* Zend Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.php.core.tests;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.concurrent.Semaphore;
import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.dltk.core.search.indexing.AbstractJob;
import org.eclipse.dltk.core.search.indexing.IndexManager;
import org.eclipse.dltk.internal.core.ModelManager;
import org.eclipse.php.core.PHPVersion;
import org.eclipse.php.core.libfolders.LibraryFolderManager;
import org.eclipse.php.core.project.ProjectOptions;
import org.eclipse.php.internal.core.Logger;
import org.eclipse.php.internal.core.project.PHPNature;
import org.eclipse.wst.validation.ValidationFramework;
/**
* Utility & support class for all PHP tests.
*
* @author Bartlomiej Laczkowski
*/
@SuppressWarnings("all")
public final class TestUtils {
public static enum ColliderType {
AUTO_BUILD, WTP_VALIDATION, LIBRARY_AUTO_DETECTION, ALL;
}
private static final class NoWaitSignalThread extends Thread {
public NoWaitSignalThread() {
super("No-Wait-Signal-Thread");
}
@Override
public void run() {
ModelManager.getModelManager().getIndexManager().waitUntilReady();
}
}
private static final class NoDelayRequest extends AbstractJob {
private final Thread noWaitSignalThread;
private final Semaphore waitForIndexerSemaphore;
private final IndexManager indexManager;
private NoDelayRequest(Thread noWaitSignalThread, Semaphore waitForIndexerSemaphore) {
this.waitForIndexerSemaphore = waitForIndexerSemaphore;
this.noWaitSignalThread = noWaitSignalThread;
this.indexManager = ModelManager.getModelManager().getIndexManager();
}
@Override
protected void run() throws CoreException, IOException {
/*
* Check if there were some new index requests added to the queue in
* the meantime, if so go back to the end of the queue.
*/
if (indexManager.awaitingJobsCount() > 1) {
noWaitSignalThread.interrupt();
NoWaitSignalThread noWaitSignalThread = new NoWaitSignalThread();
// Go back to the end of the queue
indexManager.request(new NoDelayRequest(noWaitSignalThread, waitForIndexerSemaphore));
noWaitSignalThread.start();
return;
}
// Interrupt "wait for indexer" thread (no sleeping dude...).
noWaitSignalThread.interrupt();
/*
* Requests queue is empty, we can assume that indexer has finished
* so release semaphore to move on with processing.
*/
waitForIndexerSemaphore.release();
}
@Override
protected String getName() {
return "WAIT-UNTIL-READY-NO-DELAY-JOB";
}
}
/**
* Wait for indexer to finish incoming requests.
*/
public static synchronized void waitForIndexer() {
final IndexManager indexManager = ModelManager.getModelManager().getIndexManager();
final Semaphore waitForIndexerSemaphore = new Semaphore(0);
final Thread noWaitSignalThread = new NoWaitSignalThread();
indexManager.request(new NoDelayRequest(noWaitSignalThread, waitForIndexerSemaphore));
noWaitSignalThread.start();
// Wait for indexer requests to be finished
waitForIndexerSemaphore.acquireUninterruptibly();
}
/**
* Wait for auto-build notification to occur, that is for the auto-build to
* finish.
*/
public synchronized static void waitForAutoBuild() {
boolean wasInterrupted = false;
do {
try {
Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, null);
wasInterrupted = false;
} catch (OperationCanceledException e) {
throw (e);
} catch (InterruptedException e) {
wasInterrupted = true;
}
} while (wasInterrupted);
}
/**
* Set project PHP version
*
* @param project
* @param phpVersion
* @throws CoreException
*/
public static void setProjectPhpVersion(IProject project, PHPVersion phpVersion) throws CoreException {
if (phpVersion != ProjectOptions.getPHPVersion(project)) {
ProjectOptions.setPHPVersion(phpVersion, project);
waitForIndexer();
}
}
/**
* Creates new PHP project.
*
* @param projectName
* @return new PHP project
*/
public static IProject createProject(String projectName) {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
try {
project.create(null);
project.open(null);
// configure nature
IProjectDescription desc = project.getDescription();
desc.setNatureIds(new String[] { PHPNature.ID });
project.setDescription(desc, null);
} catch (CoreException e) {
Logger.logException(e);
}
return project;
}
/**
* Creates new folder under given project.
*
* @param project
* @param folderName
* @return created folder
*/
public static IFolder createFolder(IProject project, String folderName) {
IFolder folder = project.getFolder(folderName);
try {
folder.create(true, true, null);
} catch (CoreException e) {
Logger.logException(e);
}
return folder;
}
/**
* Creates new file in related project.
*
* @param project
* @param fileName
* @param fileContent
* @return new file
*/
public static IFile createFile(IProject project, String fileName, String fileContent) {
IFile file = project.getFile(fileName);
try {
file.create(new ByteArrayInputStream(fileContent.getBytes()), true, null);
} catch (CoreException e) {
Logger.logException(e);
}
return file;
}
/**
* Creates new file in related folder.
*
* @param folder
* @param fileName
* @param fileContent
* @return new file
*/
public static IFile createFile(IFolder folder, String fileName, String fileContent) {
IFile file = folder.getFile(fileName);
try {
file.create(new ByteArrayInputStream(fileContent.getBytes()), true, null);
} catch (CoreException e) {
Logger.logException(e);
}
return file;
}
/**
* Deletes project.
*
* @param project
*/
public static void deleteProject(IProject project) {
try {
project.close(null);
project.delete(true, true, null);
} catch (CoreException e) {
Logger.logException(e);
}
}
/**
* Deletes file.
*
* @param file
*/
public static void deleteFile(IFile file) {
try {
file.delete(true, null);
} catch (CoreException e) {
Logger.logException(e);
}
}
/**
* Enables chosen features that might interfere performing tests.
*
* @param collider
*/
public static void enableColliders(ColliderType collider) {
switch (collider) {
case AUTO_BUILD: {
enableAutoBuild();
break;
}
case WTP_VALIDATION: {
enableValidation();
break;
}
case LIBRARY_AUTO_DETECTION: {
enableLibraryDetection();
break;
}
case ALL: {
enableAutoBuild();
enableValidation();
enableLibraryDetection();
break;
}
default:
break;
}
}
/**
* Disables chosen features that might interfere performing tests.
*
* @param collider
*/
public static void disableColliders(ColliderType collider) {
switch (collider) {
case AUTO_BUILD: {
disableAutoBuild();
break;
}
case WTP_VALIDATION: {
disableValidation();
break;
}
case LIBRARY_AUTO_DETECTION: {
disableLibraryDetection();
break;
}
case ALL: {
disableAutoBuild();
disableValidation();
disableLibraryDetection();
break;
}
default:
break;
}
}
/**
* Compares expected result with the actual.
*
* @param expected
* @param actual
* @return difference string or <code>null</code> in case expected result is
* equal to the actual.
*/
public static String compareContents(String expected, String actual) {
actual = actual.replaceAll("[\r\n]+", "\n").trim();
expected = expected.replaceAll("[\r\n]+", "\n").trim();
int expectedDiff = StringUtils.indexOfDifference(actual, expected);
if (expectedDiff >= 0) {
int actualDiff = StringUtils.indexOfDifference(expected, actual);
return getDiffError(expected, actual, expectedDiff, actualDiff);
}
return null;
}
/**
* Compares expected result with the actual ingoring whitespace characters
*
* @param expected
* @param actual
* @return difference string or <code>null</code> in case expected result is
* equal to the actual.
*/
public static String compareContentsIgnoreWhitespace(String expected, String actual) {
String tmpExpected = expected;
String tmpActual = actual;
String diff = StringUtils.difference(tmpExpected, tmpActual);
while (diff.length() > 0) {
String diff2 = StringUtils.difference(tmpActual, tmpExpected);
if (!Character.isWhitespace(diff.charAt(0)) && !Character.isWhitespace(diff2.charAt(0))) {
int expectedDiff = StringUtils.indexOfDifference(tmpActual, tmpExpected)
+ (expected.length() - tmpExpected.length());
int actualDiff = StringUtils.indexOfDifference(tmpExpected, tmpActual)
+ (actual.length() - tmpActual.length());
return getDiffError(expected, actual, expectedDiff, actualDiff);
}
tmpActual = diff.trim();
tmpExpected = diff2.trim();
diff = StringUtils.difference(tmpExpected, tmpActual);
}
return null;
}
private static String getDiffError(String expected, String actual, int expectedDiff, int actualDiff) {
StringBuilder errorBuf = new StringBuilder();
errorBuf.append("\nEXPECTED:\n--------------\n");
errorBuf.append(expected.substring(0, expectedDiff)).append("*****").append(expected.substring(expectedDiff));
errorBuf.append("\n\nACTUAL:\n--------------\n");
errorBuf.append(actual.substring(0, actualDiff)).append("*****").append(actual.substring(actualDiff));
return errorBuf.toString();
}
private static void enableAutoBuild() {
if (!ResourcesPlugin.getWorkspace().isAutoBuilding()) {
IWorkspaceDescription workspaceDescription = ResourcesPlugin.getWorkspace().getDescription();
workspaceDescription.setAutoBuilding(true);
try {
ResourcesPlugin.getWorkspace().setDescription(workspaceDescription);
} catch (CoreException e) {
Logger.logException(e);
}
}
}
private static void enableValidation() {
ValidationFramework.getDefault().suspendAllValidation(false);
}
private static void enableLibraryDetection() {
LibraryFolderManager.getInstance().suspendAllDetection(false);
}
private static void disableAutoBuild() {
if (ResourcesPlugin.getWorkspace().isAutoBuilding()) {
IWorkspaceDescription workspaceDescription = ResourcesPlugin.getWorkspace().getDescription();
workspaceDescription.setAutoBuilding(false);
try {
ResourcesPlugin.getWorkspace().setDescription(workspaceDescription);
} catch (CoreException e) {
Logger.logException(e);
}
}
}
private static void disableValidation() {
ValidationFramework.getDefault().suspendAllValidation(true);
}
private static void disableLibraryDetection() {
LibraryFolderManager.getInstance().suspendAllDetection(true);
}
}