/** Tests a builder that requests deltas for closed and missing projects. */
  public void testRequestMissingProject() {
    // add builder and do an initial build to get the instance
    try {
      addBuilder(project1, DeltaVerifierBuilder.BUILDER_NAME);
      project1.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
    } catch (CoreException e) {
      fail("1.0", e);
    }
    final DeltaVerifierBuilder builder = DeltaVerifierBuilder.getInstance();
    assertTrue("1.1", builder != null);
    // always check deltas for all projects
    final IProject[] allProjects = new IProject[] {project1, project2, project3, project4};
    try {
      project2.close(getMonitor());
      project3.delete(IResource.ALWAYS_DELETE_PROJECT_CONTENT, getMonitor());
    } catch (CoreException e1) {
      fail("1.99", e1);
    }
    builder.checkDeltas(allProjects);

    // modify a file in project1 to force an autobuild
    try {
      file1.setContents(getRandomContents(), IResource.NONE, getMonitor());
    } catch (CoreException e2) {
      fail("2.99", e2);
    }
  }
  /**
   * In this test, only project1 has a builder, but it is interested in deltas from the other
   * projects. We vary the set of projects that are changed, and the set of projects we request
   * deltas for.
   */
  public void testDeltas() {
    // add builder and do an initial build to get the instance
    try {
      setAutoBuilding(false);
      addBuilder(project1, DeltaVerifierBuilder.BUILDER_NAME);
      project1.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
    } catch (CoreException e) {
      fail("1.0", e);
    }
    final DeltaVerifierBuilder builder = DeltaVerifierBuilder.getInstance();
    assertTrue("1.1", builder != null);
    // always check deltas for all projects
    final IProject[] allProjects = new IProject[] {project1, project2, project3, project4};
    builder.checkDeltas(allProjects);

    // hold onto the set of requested projects here
    final IProject[][] previousRequest = new IProject[][] {new IProject[] {project1}};
    // hold onto projects that have been modified since the last time the builder was run.
    final HashSet<IProject> previouslyModified = new HashSet<IProject>();
    new TestPerformer("testDeltas") {
      public Object[] interestingOldState(Object[] args) throws Exception {
        return null;
      }

      public Object invokeMethod(Object[] args, int count) throws Exception {
        // set requests for next build
        IProject[] requested = (IProject[]) args[0];
        IProject[] toModify = (IProject[]) args[1];
        builder.reset();
        builder.requestDeltas(requested);
        // do the build
        dirty(toModify);
        Object result = previousRequest[0];
        if (builder.wasBuilt()) {
          // if the builder ran, update previous request
          previousRequest[0] = requested;
          previouslyModified.clear();
        } else {
          previouslyModified.addAll(Arrays.asList(toModify));
        }
        return result;
      }

      public boolean shouldFail(Object[] args, int count) {
        return false;
      }

      public boolean wasSuccess(Object[] args, Object result, Object[] oldState) throws Exception {
        HashSet<IProject> requested = new HashSet<IProject>(Arrays.asList((IProject[]) result));
        HashSet<IProject> modified = new HashSet<IProject>(Arrays.asList((IProject[]) args[1]));
        modified.addAll(previouslyModified);
        HashSet<IProject> obtained = new HashSet<IProject>();
        if (!builder.getReceivedDeltas().isEmpty()) obtained.addAll(builder.getReceivedDeltas());
        ArrayList<IProject> emptyDeltas = builder.getEmptyDeltas();

        // the builder's project is implicitly requested
        requested.add(builder.getProject());

        for (int i = 0; i < allProjects.length; i++) {
          IProject project = allProjects[i];
          boolean wasObtained = obtained.contains(project);
          boolean wasRequested = requested.contains(project);
          boolean wasModified = modified.contains(project);
          boolean wasEmpty = emptyDeltas.contains(project);
          if (wasObtained) {
            // every delta we obtained should have been requested and (modified or empty)
            if (!wasRequested || !(wasModified || wasEmpty)) return false;
          } else {
            // if delta was not obtained, then must be unchanged or not requested
            if (wasRequested && wasModified) return false;
          }
        }
        return true;
      }
    }.performTest(new Object[][] {interestingProjects(), reverse(interestingProjects())});
  }