/*******************************************************************************
* Copyright (c) 2011 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.validation.test;
import java.io.InputStream;
import java.io.Reader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Map;
import junit.framework.TestCase;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFileState;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IPathVariableManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourceAttributes;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.jboss.tools.common.base.test.validation.ValidationExceptionLogger;
import org.jboss.tools.common.base.test.validation.ValidationExceptionTest;
import org.jboss.tools.common.validation.ContextValidationHelper;
import org.jboss.tools.common.validation.ValidatorManager;
/**
* @author Alexey Kazakov
*/
public class SynchronizationTest extends TestCase {
static final IProject CHANGED_PROJECT_1 = ResourcesPlugin.getWorkspace().getRoot().getProject("ChangedProject1"); // Fake project which is "changed" by user. Thread 1.
static final IProject PROJECT_A_1 = ResourcesPlugin.getWorkspace().getRoot().getProject("ProjectA1"); // Fake root project. Depends on ChangedProject1.
static final IProject CHANGED_PROJECT_B_1 = ResourcesPlugin.getWorkspace().getRoot().getProject("ChangedProjectB1"); // Fake project which is "changed" by user. Thread 2. Depends on ChangedProject1
static final IProject PROJECT_B_2 = ResourcesPlugin.getWorkspace().getRoot().getProject("ProjectB2"); // Fake root project. Depends on ChangedProjectB1.
static final IProject PROJECT_B_A_1 = ResourcesPlugin.getWorkspace().getRoot().getProject("ProjectBA1"); // Fake root project. Depends on ChangedProjectB1.
public void testSynchronizedValidatotion() throws Exception {
ValidationExceptionLogger logger = new ValidationExceptionLogger();
final ContextValidationHelper helperThread1 = new ContextValidationHelper();
helperThread1.setProject(CHANGED_PROJECT_B_1);
FakeFile changeFileProjectB1 = new FakeFile(CHANGED_PROJECT_B_1, "ChangeFileProjectB1.java");
helperThread1.registerResource(changeFileProjectB1);
helperThread1.setValidationFileURIs(new ArrayList<String>());
final ValidatorManager managerThread1 = new ValidatorManager();
final ContextValidationHelper helperThread2 = new ContextValidationHelper();
helperThread2.setProject(CHANGED_PROJECT_1);
FakeFile changeFileProject1 = new FakeFile(CHANGED_PROJECT_1, "ChangeFileProject1.java");
helperThread2.registerResource(changeFileProject1);
helperThread2.setValidationFileURIs(new ArrayList<String>());
final ValidatorManager managerThread2 = new ValidatorManager();
final ThreadHolder threadHolder = new ThreadHolder();
for (int i = 1; i < 4; i++) {
Runnable thread1 = new Runnable() {
public void run() {
try {
managerThread1.validate(helperThread1, null);
} catch (ValidationException e) {
threadHolder.setException(e);
} finally {
threadHolder.finish();
}
}
};
Runnable thread2 = new Runnable() {
public void run() {
try {
managerThread2.validate(helperThread2, null);
} catch (ValidationException e) {
threadHolder.setException(e);
} finally {
threadHolder.finish();
}
}
};
threadHolder.start();
new Thread(thread1).start();
threadHolder.start();
new Thread(thread2).start();
// Wait for all validators
while (!threadHolder.isReady()) {
Thread.sleep(10);
}
if(threadHolder.getException()!=null) {
throw new Exception(threadHolder.getException());
}
ValidationExceptionTest.assertExceptionsIsEmpty(logger);
assertProjectValidation(i, PROJECT_A_1);
assertProjectValidation(i, PROJECT_B_2);
assertProjectValidation(i, PROJECT_B_A_1);
}
}
private void assertProjectValidation(int attempt, IProject project) {
assertTrue("Project " + project.getName() + " has not been validated. Attemp #" + attempt, TestSynchronizationValidator.isProjectValidated(project));
}
private static class ThreadHolder {
private Exception exception;
private int startedValidators;
public synchronized void finish() {
startedValidators--;
}
public synchronized void start() {
startedValidators++;
}
public synchronized boolean isReady() {
return startedValidators==0;
}
public synchronized Exception getException() {
return exception;
}
public synchronized void setException(Exception exception) {
this.exception = exception;
}
}
private static class FakeFile implements IFile {
private IProject project;
private String name;
public FakeFile(IProject project, String name) {
this.project = project;
this.name = name;
}
public boolean exists() {
return true;
}
public String getFileExtension() {
return name.substring(name.lastIndexOf('.'));
}
public IContainer getParent() {
return project;
}
public IProject getProject() {
return project;
}
public boolean isAccessible() {
return true;
}
public void accept(IResourceProxyVisitor visitor, int memberFlags) throws CoreException {}
public void accept(IResourceVisitor visitor) throws CoreException {}
public void accept(IResourceVisitor visitor, int depth, boolean includePhantoms) throws CoreException {}
public void accept(IResourceVisitor visitor, int depth, int memberFlags) throws CoreException {}
public void clearHistory(IProgressMonitor monitor) throws CoreException {}
public void copy(IPath destination, boolean force, IProgressMonitor monitor) throws CoreException {}
public void copy(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException {}
public void copy(IProjectDescription description, boolean force, IProgressMonitor monitor) throws CoreException {}
public void copy(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException {}
public IMarker createMarker(String type) throws CoreException {return null;}
public IResourceProxy createProxy() {return null;}
public void delete(boolean force, IProgressMonitor monitor) throws CoreException {}
public void delete(int updateFlags, IProgressMonitor monitor) throws CoreException {}
public void deleteMarkers(String type, boolean includeSubtypes, int depth) throws CoreException {}
public IMarker findMarker(long id) throws CoreException {return null;}
public IMarker[] findMarkers(String type, boolean includeSubtypes, int depth) throws CoreException {return null;}
public int findMaxProblemSeverity(String type, boolean includeSubtypes, int depth) throws CoreException {return 0;}
public long getLocalTimeStamp() {return 0;}
public IPath getLocation() {return null;}
public URI getLocationURI() {return null;}
public IMarker getMarker(long id) {return null;}
public long getModificationStamp() {return 0;}
public IPathVariableManager getPathVariableManager() {return null;}
public Map<QualifiedName, String> getPersistentProperties() throws CoreException {return null;}
public String getPersistentProperty(QualifiedName key) throws CoreException {return null;}
public IPath getProjectRelativePath() {return null;}
public IPath getRawLocation() {return null;}
public URI getRawLocationURI() {return null;}
public ResourceAttributes getResourceAttributes() {return null;}
public Map<QualifiedName, Object> getSessionProperties() throws CoreException {return null;}
public Object getSessionProperty(QualifiedName key) throws CoreException {return null;}
public int getType() {return 0;}
public IWorkspace getWorkspace() {return null;}
public boolean isDerived() {return false;}
public boolean isDerived(int options) {return false;}
public boolean isHidden() {return false;}
public boolean isHidden(int options) {return false;}
public boolean isLinked() {return false;}
public boolean isVirtual() {return false;}
public boolean isLinked(int options) {return false;}
public boolean isLocal(int depth) {return false;}
public boolean isPhantom() {return false;}
public boolean isSynchronized(int depth) {return false;}
public boolean isTeamPrivateMember() {return false;}
public boolean isTeamPrivateMember(int options) {return false;}
public void move(IPath destination, boolean force, IProgressMonitor monitor) throws CoreException {}
public void move(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException {}
public void move(IProjectDescription description, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException {}
public void move(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException {}
public void refreshLocal(int depth, IProgressMonitor monitor) throws CoreException {}
public void revertModificationStamp(long value) throws CoreException {}
public void setDerived(boolean isDerived) throws CoreException {}
public void setDerived(boolean isDerived, IProgressMonitor monitor) throws CoreException {}
public void setHidden(boolean isHidden) throws CoreException {}
public void setLocal(boolean flag, int depth, IProgressMonitor monitor) throws CoreException {}
public long setLocalTimeStamp(long value) throws CoreException {return 0;}
public void setPersistentProperty(QualifiedName key, String value) throws CoreException {}
public void setReadOnly(boolean readOnly) {}
public void setResourceAttributes(ResourceAttributes attributes) throws CoreException {}
public void setSessionProperty(QualifiedName key, Object value) throws CoreException {}
public void setTeamPrivateMember(boolean isTeamPrivate) throws CoreException {}
public void touch(IProgressMonitor monitor) throws CoreException {}
public Object getAdapter(Class adapter) {return null;}
public boolean contains(ISchedulingRule rule) {return false;}
public boolean isConflicting(ISchedulingRule rule) {return false;}
public void appendContents(InputStream source, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException {}
public void appendContents(InputStream source, int updateFlags, IProgressMonitor monitor) throws CoreException {}
public void create(InputStream source, boolean force, IProgressMonitor monitor) throws CoreException {}
public void create(InputStream source, int updateFlags, IProgressMonitor monitor) throws CoreException {}
public void createLink(IPath localLocation, int updateFlags, IProgressMonitor monitor) throws CoreException {}
public void createLink(URI location, int updateFlags, IProgressMonitor monitor) throws CoreException {}
public void delete(boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException {}
public String getCharset() throws CoreException {return null;}
public String getCharset(boolean checkImplicit) throws CoreException {return null;}
public String getCharsetFor(Reader reader) throws CoreException {return null;}
public IContentDescription getContentDescription() throws CoreException {return null;}
public InputStream getContents() throws CoreException {return null;}
public InputStream getContents(boolean force) throws CoreException {return null;}
public int getEncoding() throws CoreException {return 0;}
public IPath getFullPath() {return null;}
public IFileState[] getHistory(IProgressMonitor monitor) throws CoreException {return null;}
public String getName() {return null;}
public boolean isReadOnly() {return false;}
public void move(IPath destination, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException {}
public void setCharset(String newCharset) throws CoreException {}
public void setCharset(String newCharset, IProgressMonitor monitor) throws CoreException {}
public void setContents(InputStream source, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException {}
public void setContents(IFileState source, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException {}
public void setContents(InputStream source, int updateFlags, IProgressMonitor monitor) throws CoreException {}
public void setContents(IFileState source, int updateFlags, IProgressMonitor monitor) throws CoreException {}
public void accept(IResourceProxyVisitor visitor, int depth, int memberFlags) throws CoreException {}
}
}