blob: d44d1d696c39c473510cfef2a39f91a83d8d4da5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 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
* James Blackburn (Broadcom Corp.) - ongoing development
*******************************************************************************/
package org.eclipse.core.tests.internal.builders;
import java.util.ArrayList;
import java.util.Map;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.tests.resources.ResourceDeltaVerifier;
import org.junit.Assert;
/**
* This classes poses as a builder, and makes sure that the delta supplied to
* the builder is as expected. Most of the work is forwarded to a
* ResourceDeltaVerifier.
*/
public class DeltaVerifierBuilder extends TestBuilder {
public static final String BUILDER_NAME = "org.eclipse.core.tests.resources.deltaverifierbuilder";
/**
* The singleton builder instance
*/
protected static DeltaVerifierBuilder fgSingleton;
/**
* The resource delta verifier that asserts the delta structure. Sharing it
* between builders means we can do things like shutdown the project,
* re-open, build, and assert the delta is appropriate.
*/
protected static final ResourceDeltaVerifier verifier = new ResourceDeltaVerifier();
/** The projects to check deltas for (may be null) */
protected IProject[] checkDeltas;
/**
* Whether the last incremental build was empty
*/
protected boolean deltaWasEmpty = false;
/** The empty deltas that were received */
protected ArrayList<IProject> emptyDeltas = new ArrayList<>();
/** The deltas that were actually received */
protected ArrayList<IProject> receivedDeltas = new ArrayList<>();
/** The projects to request deltas for (may be null) */
protected IProject[] requestedDeltas;
/**
* Whether the last build was full or batch
*/
protected int triggerForLastBuild = 0;
/**
* Returns the singleton instance
*/
public static DeltaVerifierBuilder getInstance() {
if (fgSingleton == null) {
new DeltaVerifierBuilder();
}
return fgSingleton;
}
/**
* Captures the builder instantiated through reflection
*/
public DeltaVerifierBuilder() {
if (fgSingleton != null) {
//copy interesting data from old singleton
this.triggerForLastBuild = fgSingleton.triggerForLastBuild;
this.deltaWasEmpty = fgSingleton.deltaWasEmpty;
this.requestedDeltas = fgSingleton.requestedDeltas;
this.checkDeltas = fgSingleton.checkDeltas;
this.receivedDeltas = fgSingleton.receivedDeltas;
this.emptyDeltas = fgSingleton.emptyDeltas;
}
fgSingleton = this;
}
/**
* Signals to the comparer that the given resource is expected to change in
* the specified way. The change flags should be set to zero if no change is
* expected.
*
* @param resource
* the resource that is expected to change
* @param topLevelParent
* Do not added expected changes above this parent
* @param status
* the type of change (ADDED, REMOVED, CHANGED)
* @param changeFlags
* the type of change (CONTENT, SYNC, etc)
* @param movedPath
* or null
* @see IResourceConstants
*/
public void addExpectedChange(IResource resource, IResource topLevelParent, int status, int changeFlags) {
verifier.addExpectedChange(resource, topLevelParent, status, changeFlags, null, null);
}
/**
* Signals to the comparer that the given resource is expected to change in
* the specified way. The change flags should be set to zero if no change is
* expected.
*
* @param resource
* the resource that is expected to change
* @param topLevelParent
* Do not added expected changes above this parent
* @param status
* the type of change (ADDED, REMOVED, CHANGED)
* @param changeFlags
* the type of change (CONTENT, SYNC, etc)
* @param movedPath
* or null
* @see IResourceConstants
*/
public void addExpectedChange(IResource resource, IResource topLevelParent, int status, int changeFlags, IPath movedFromPath, IPath movedToPath) {
verifier.addExpectedChange(resource, topLevelParent, status, changeFlags, movedFromPath, movedToPath);
}
/**
* Like a wiley restaurant critic, this method masquerades as a builder, but
* is actually verifying that the provided delta is correct.
*/
@Override
protected IProject[] build(int kind, Map<String, String> args, IProgressMonitor monitor) throws CoreException {
super.build(kind, args, monitor);
triggerForLastBuild = kind;
doCheckDeltas();
IResourceDelta delta = getDelta(getProject());
deltaWasEmpty = delta == null || delta.getKind() == 0;
// Check delta
if (!deltaWasEmpty) {
verifier.verifyDelta(delta);
}
return getRequestedDeltas();
}
/**
* Indicates which projects to check receipt of deltas for.
*/
public void checkDeltas(IProject[] projects) {
checkDeltas = projects;
}
@Override
protected void clean(IProgressMonitor monitor) {
triggerForLastBuild = CLEAN_BUILD;
}
/**
* Asks the platform for the deltas for a set of projects, and notes which
* deltas were actually returned.
*/
protected void doCheckDeltas() {
if (checkDeltas == null) {
return;
}
receivedDeltas.clear();
for (IProject checkDelta : checkDeltas) {
IResourceDelta delta = getDelta(checkDelta);
if (delta != null) {
receivedDeltas.add(checkDelta);
//check if the delta was empty
if (delta.getKind() == IResourceDelta.NO_CHANGE && delta.getAffectedChildren().length == 0) {
emptyDeltas.add(checkDelta);
}
//regression test -- ensure delta resource is non null
Assert.assertTrue("Non-null delta", delta.getResource() != null);
Assert.assertTrue("Delta rooted at project", delta.getResource().getType() == IResource.PROJECT);
}
}
}
/**
* Signals that an empty build has occurred, so the build method hasn't been
* called but the state should still be considered valid.
*/
public void emptyBuild() throws CoreException {
build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null, null);
}
/**
* Returns the empty deltas received during the last build.
*/
public ArrayList<IProject> getEmptyDeltas() {
return emptyDeltas;
}
/**
* Returns a message that describes the result of the resource delta
* verification checks.
*/
public String getMessage() {
String msg;
if (deltaWasEmpty) {
if (verifier.hasExpectedChanges()) {
msg = "Had expected changes but delta was empty";
} else {
msg = "No Delta";
}
} else {
msg = verifier.getMessage();
}
return msg;
}
/**
* Returns the projects for the deltas that were actually received during
* the last build.
*/
public ArrayList<IProject> getReceivedDeltas() {
return receivedDeltas;
}
/**
* Returns the projects to request deltas for next build.
*/
protected IProject[] getRequestedDeltas() {
return requestedDeltas == null ? new IProject[0] : requestedDeltas;
}
/**
* Returns whether the resource delta passed all verification checks. An
* empty delta is valid if no changes were expected.
*/
public boolean isDeltaValid() {
return (deltaWasEmpty && !verifier.hasExpectedChanges()) || verifier.isDeltaValid();
}
/**
* Indicates that the builder should request deltas for the given projects.
*/
public void requestDeltas(IProject[] projects) {
requestedDeltas = projects;
receivedDeltas.clear();
emptyDeltas.clear();
}
/*
* @see TestBuilder#reset()
*/
@Override
public void reset() {
super.reset();
triggerForLastBuild = 0;
if (verifier != null) {
verifier.reset();
}
}
public boolean wasAutoBuild() {
return triggerForLastBuild == IncrementalProjectBuilder.AUTO_BUILD;
}
/**
* Returns true if the builder has been invoked since the last time it was
* reset, and false otherwise.
*/
public boolean wasBuilt() {
return triggerForLastBuild != 0;
}
public boolean wasCleanBuild() {
return triggerForLastBuild == IncrementalProjectBuilder.CLEAN_BUILD;
}
public boolean wasFullBuild() {
return triggerForLastBuild == IncrementalProjectBuilder.FULL_BUILD;
}
public boolean wasIncrementalBuild() {
return triggerForLastBuild == IncrementalProjectBuilder.INCREMENTAL_BUILD;
}
}