Program: 27929
Project: 27929
Buggy source:
/** 
 * Verifies that the compiler pass's JS output matches the expected output and (optionally) that an expected warning is issued. Or, if an error is expected, this method just verifies that the error is encountered.
 * @param compiler A compiler that has been initialized via{@link Compiler#init}
 * @param expected Expected output, or null if an error is expected
 * @param error Expected error, or null if no error is expected
 * @param warning Expected warning, or null if no warning is expected
 * @param description The description of the expected warning,or null if no warning is expected or if the warning's description should not be examined
 */
private void test(Compiler compiler,String[] expected,DiagnosticType error,DiagnosticType warning,String description){
  RecentChange recentChange=new RecentChange();
  compiler.addChangeHandler(recentChange);
  Node root=compiler.parseInputs();
  assertTrue("String_Node_Str" + Joiner.on("String_Node_Str").join(compiler.getErrors()),root != null);
  if (!expectParseWarningsThisTest) {
    assertTrue("String_Node_Str" + Joiner.on("String_Node_Str").join(compiler.getWarnings()),compiler.getWarnings().length == 0);
  }
  if (astValidationEnabled) {
    (new AstValidator()).validateRoot(root);
  }
  Node externsRoot=root.getFirstChild();
  Node mainRoot=root.getLastChild();
  Node rootClone=root.cloneTree();
  Node externsRootClone=rootClone.getFirstChild();
  Node mainRootClone=rootClone.getLastChild();
  Map<Node,Node> mtoc=NodeUtil.mapMainToClone(mainRoot,mainRootClone);
  int numRepetitions=getNumRepetitions();
  ErrorManager[] errorManagers=new ErrorManager[numRepetitions];
  int aggregateWarningCount=0;
  List<JSError> aggregateWarnings=Lists.newArrayList();
  boolean hasCodeChanged=false;
  assertFalse("String_Node_Str",recentChange.hasCodeChanged());
  for (int i=0; i < numRepetitions; ++i) {
    if (compiler.getErrorCount() == 0) {
      errorManagers[i]=new BlackHoleErrorManager(compiler);
      if (closurePassEnabled && i == 0) {
        recentChange.reset();
        new ProcessClosurePrimitives(compiler,null,CheckLevel.ERROR).process(null,mainRoot);
        hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      }
      if (typeCheckEnabled && i == 0) {
        TypeCheck check=createTypeCheck(compiler,typeCheckLevel);
        check.processForTesting(externsRoot,mainRoot);
      }
      if (normalizeEnabled && i == 0) {
        normalizeActualCode(compiler,externsRoot,mainRoot);
      }
      if (markNoSideEffects && i == 0) {
        MarkNoSideEffectCalls mark=new MarkNoSideEffectCalls(compiler);
        mark.process(externsRoot,mainRoot);
      }
      recentChange.reset();
      getProcessor(compiler).process(externsRoot,mainRoot);
      if (astValidationEnabled) {
        (new AstValidator()).validateRoot(root);
      }
      if (checkLineNumbers) {
        (new LineNumberCheck(compiler)).process(externsRoot,mainRoot);
      }
      hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      aggregateWarningCount+=errorManagers[i].getWarningCount();
      aggregateWarnings.addAll(Lists.newArrayList(compiler.getWarnings()));
      if (normalizeEnabled) {
        boolean verifyDeclaredConstants=true;
        new Normalize.VerifyConstants(compiler,verifyDeclaredConstants).process(externsRoot,mainRoot);
      }
    }
  }
  if (error == null) {
    assertEquals("String_Node_Str" + Joiner.on("String_Node_Str").join(compiler.getErrors()),0,compiler.getErrorCount());
    ErrorManager symbolTableErrorManager=new BlackHoleErrorManager(compiler);
    Node expectedRoot=null;
    if (expected != null) {
      expectedRoot=parseExpectedJs(expected);
      expectedRoot.detachFromParent();
    }
    JSError[] stErrors=symbolTableErrorManager.getErrors();
    if (expectedSymbolTableError != null) {
      assertEquals("String_Node_Str",1,stErrors.length);
      assertEquals(expectedSymbolTableError,stErrors[0].getType());
    }
 else {
      assertEquals("String_Node_Str" + Joiner.on("String_Node_Str").join(stErrors),0,stErrors.length);
    }
    if (warning == null) {
      assertEquals("String_Node_Str" + Joiner.on("String_Node_Str").join(aggregateWarnings),0,aggregateWarningCount);
    }
 else {
      assertEquals("String_Node_Str" + numRepetitions + "String_Node_Str",numRepetitions,aggregateWarningCount);
      for (int i=0; i < numRepetitions; ++i) {
        JSError[] warnings=errorManagers[i].getWarnings();
        JSError actual=warnings[0];
        assertEquals(warning,actual.getType());
        if (!allowSourcelessWarnings) {
          assertTrue("String_Node_Str",actual.sourceName != null && !actual.sourceName.isEmpty());
          assertTrue("String_Node_Str",-1 != actual.lineNumber);
          assertTrue("String_Node_Str",-1 != actual.getCharno());
        }
        if (description != null) {
          assertEquals(description,actual.description);
        }
      }
    }
    if (normalizeEnabled) {
      normalizeActualCode(compiler,externsRootClone,mainRootClone);
    }
    boolean codeChange=!mainRootClone.isEquivalentTo(mainRoot);
    boolean externsChange=!externsRootClone.isEquivalentTo(externsRoot);
    if (externsChange && !allowExternsChanges) {
      String explanation=externsRootClone.checkTreeEquals(externsRoot);
      fail("String_Node_Str" + "String_Node_Str" + compiler.toSource(externsRootClone) + "String_Node_Str"+ compiler.toSource(externsRoot)+ "String_Node_Str"+ explanation);
    }
    if (!codeChange && !externsChange) {
      assertFalse("String_Node_Str" + "String_Node_Str",hasCodeChanged);
    }
 else {
      assertTrue("String_Node_Str",hasCodeChanged);
    }
    NodeUtil.verifyScopeChanges(mtoc,mainRoot,false);
    if (expected != null) {
      if (compareAsTree) {
        String explanation=expectedRoot.checkTreeEquals(mainRoot);
        assertNull("String_Node_Str" + compiler.toSource(expectedRoot) + "String_Node_Str"+ compiler.toSource(mainRoot)+ "String_Node_Str"+ explanation,explanation);
      }
 else       if (expected != null) {
        assertEquals(Joiner.on("String_Node_Str").join(expected),compiler.toSource(mainRoot));
      }
    }
    Node normalizeCheckRootClone=root.cloneTree();
    Node normalizeCheckExternsRootClone=normalizeCheckRootClone.getFirstChild();
    Node normalizeCheckMainRootClone=normalizeCheckRootClone.getLastChild();
    new PrepareAst(compiler).process(normalizeCheckExternsRootClone,normalizeCheckMainRootClone);
    String explanation=normalizeCheckMainRootClone.checkTreeEquals(mainRoot);
    assertNull("String_Node_Str" + compiler.toSource(normalizeCheckMainRootClone) + "String_Node_Str"+ compiler.toSource(mainRoot)+ "String_Node_Str"+ explanation,explanation);
    if (normalizeEnabled) {
      new Normalize(compiler,true).process(normalizeCheckExternsRootClone,normalizeCheckMainRootClone);
      explanation=normalizeCheckMainRootClone.checkTreeEquals(mainRoot);
      assertNull("String_Node_Str" + compiler.toSource(normalizeCheckMainRootClone) + "String_Node_Str"+ compiler.toSource(mainRoot)+ "String_Node_Str"+ explanation,explanation);
    }
  }
 else {
    String errors="String_Node_Str";
    for (    JSError actualError : compiler.getErrors()) {
      errors+=actualError.description + "String_Node_Str";
    }
    assertEquals("String_Node_Str" + errors,1,compiler.getErrorCount());
    assertEquals(errors,error,compiler.getErrors()[0].getType());
    if (warning != null) {
      String warnings="String_Node_Str";
      for (      JSError actualError : compiler.getWarnings()) {
        warnings+=actualError.description + "String_Node_Str";
      }
      assertEquals("String_Node_Str" + warnings,1,compiler.getWarningCount());
      assertEquals(warnings,warning,compiler.getWarnings()[0].getType());
    }
  }
}

Fixed version (ground truth):
/** 
 * Verifies that the compiler pass's JS output matches the expected output and (optionally) that an expected warning is issued. Or, if an error is expected, this method just verifies that the error is encountered.
 * @param compiler A compiler that has been initialized via{@link Compiler#init}
 * @param expected Expected output, or null if an error is expected
 * @param error Expected error, or null if no error is expected
 * @param warning Expected warning, or null if no warning is expected
 * @param description The description of the expected warning,or null if no warning is expected or if the warning's description should not be examined
 */
private void test(Compiler compiler,String[] expected,DiagnosticType error,DiagnosticType warning,String description){
  RecentChange recentChange=new RecentChange();
  compiler.addChangeHandler(recentChange);
  Node root=compiler.parseInputs();
  assertTrue("String_Node_Str" + Joiner.on("String_Node_Str").join(compiler.getErrors()),root != null);
  if (!expectParseWarningsThisTest) {
    assertTrue("String_Node_Str" + Joiner.on("String_Node_Str").join(compiler.getWarnings()),compiler.getWarnings().length == 0);
  }
  if (astValidationEnabled) {
    (new AstValidator()).validateRoot(root);
  }
  Node externsRoot=root.getFirstChild();
  Node mainRoot=root.getLastChild();
  Node rootClone=root.cloneTree();
  Node externsRootClone=rootClone.getFirstChild();
  Node mainRootClone=rootClone.getLastChild();
  Map<Node,Node> mtoc=NodeUtil.mapMainToClone(mainRoot,mainRootClone);
  int numRepetitions=getNumRepetitions();
  ErrorManager[] errorManagers=new ErrorManager[numRepetitions];
  int aggregateWarningCount=0;
  List<JSError> aggregateWarnings=Lists.newArrayList();
  boolean hasCodeChanged=false;
  assertFalse("String_Node_Str",recentChange.hasCodeChanged());
  for (int i=0; i < numRepetitions; ++i) {
    if (compiler.getErrorCount() == 0) {
      errorManagers[i]=new BlackHoleErrorManager(compiler);
      if (closurePassEnabled && i == 0) {
        recentChange.reset();
        new ProcessClosurePrimitives(compiler,null,CheckLevel.ERROR).process(null,mainRoot);
        hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      }
      if (typeCheckEnabled && i == 0) {
        TypeCheck check=createTypeCheck(compiler,typeCheckLevel);
        check.processForTesting(externsRoot,mainRoot);
      }
      if (normalizeEnabled && i == 0) {
        normalizeActualCode(compiler,externsRoot,mainRoot);
      }
      if (markNoSideEffects && i == 0) {
        MarkNoSideEffectCalls mark=new MarkNoSideEffectCalls(compiler);
        mark.process(externsRoot,mainRoot);
      }
      recentChange.reset();
      getProcessor(compiler).process(externsRoot,mainRoot);
      if (astValidationEnabled) {
        (new AstValidator()).validateRoot(root);
      }
      if (checkLineNumbers) {
        (new LineNumberCheck(compiler)).process(externsRoot,mainRoot);
      }
      hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      aggregateWarningCount+=errorManagers[i].getWarningCount();
      aggregateWarnings.addAll(Lists.newArrayList(compiler.getWarnings()));
      if (normalizeEnabled) {
        boolean verifyDeclaredConstants=true;
        new Normalize.VerifyConstants(compiler,verifyDeclaredConstants).process(externsRoot,mainRoot);
      }
    }
  }
  if (error == null) {
    assertEquals("String_Node_Str" + Joiner.on("String_Node_Str").join(compiler.getErrors()),0,compiler.getErrorCount());
    ErrorManager symbolTableErrorManager=new BlackHoleErrorManager(compiler);
    Node expectedRoot=null;
    if (expected != null) {
      expectedRoot=parseExpectedJs(expected);
      expectedRoot.detachFromParent();
    }
    JSError[] stErrors=symbolTableErrorManager.getErrors();
    if (expectedSymbolTableError != null) {
      assertEquals("String_Node_Str",1,stErrors.length);
      assertEquals(expectedSymbolTableError,stErrors[0].getType());
    }
 else {
      assertEquals("String_Node_Str" + Joiner.on("String_Node_Str").join(stErrors),0,stErrors.length);
    }
    if (warning == null) {
      assertEquals("String_Node_Str" + Joiner.on("String_Node_Str").join(aggregateWarnings),0,aggregateWarningCount);
    }
 else {
      assertEquals("String_Node_Str" + numRepetitions + "String_Node_Str",numRepetitions,aggregateWarningCount);
      for (int i=0; i < numRepetitions; ++i) {
        JSError[] warnings=errorManagers[i].getWarnings();
        JSError actual=warnings[0];
        assertEquals(warning,actual.getType());
        if (!allowSourcelessWarnings) {
          assertTrue("String_Node_Str",actual.sourceName != null && !actual.sourceName.isEmpty());
          assertTrue("String_Node_Str",-1 != actual.lineNumber);
          assertTrue("String_Node_Str",-1 != actual.getCharno());
        }
        if (description != null) {
          assertEquals(description,actual.description);
        }
      }
    }
    if (normalizeEnabled) {
      normalizeActualCode(compiler,externsRootClone,mainRootClone);
    }
    boolean codeChange=!mainRootClone.isEquivalentTo(mainRoot);
    boolean externsChange=!externsRootClone.isEquivalentTo(externsRoot);
    if (externsChange && !allowExternsChanges) {
      String explanation=externsRootClone.checkTreeEquals(externsRoot);
      fail("String_Node_Str" + "String_Node_Str" + compiler.toSource(externsRootClone) + "String_Node_Str"+ compiler.toSource(externsRoot)+ "String_Node_Str"+ explanation);
    }
    if (!codeChange && !externsChange) {
      assertFalse("String_Node_Str" + "String_Node_Str",hasCodeChanged);
    }
 else {
      assertTrue("String_Node_Str",hasCodeChanged);
    }
    NodeUtil.verifyScopeChanges(mtoc,mainRoot,false,compiler);
    if (expected != null) {
      if (compareAsTree) {
        String explanation=expectedRoot.checkTreeEquals(mainRoot);
        assertNull("String_Node_Str" + compiler.toSource(expectedRoot) + "String_Node_Str"+ compiler.toSource(mainRoot)+ "String_Node_Str"+ explanation,explanation);
      }
 else       if (expected != null) {
        assertEquals(Joiner.on("String_Node_Str").join(expected),compiler.toSource(mainRoot));
      }
    }
    Node normalizeCheckRootClone=root.cloneTree();
    Node normalizeCheckExternsRootClone=normalizeCheckRootClone.getFirstChild();
    Node normalizeCheckMainRootClone=normalizeCheckRootClone.getLastChild();
    new PrepareAst(compiler).process(normalizeCheckExternsRootClone,normalizeCheckMainRootClone);
    String explanation=normalizeCheckMainRootClone.checkTreeEquals(mainRoot);
    assertNull("String_Node_Str" + compiler.toSource(normalizeCheckMainRootClone) + "String_Node_Str"+ compiler.toSource(mainRoot)+ "String_Node_Str"+ explanation,explanation);
    if (normalizeEnabled) {
      new Normalize(compiler,true).process(normalizeCheckExternsRootClone,normalizeCheckMainRootClone);
      explanation=normalizeCheckMainRootClone.checkTreeEquals(mainRoot);
      assertNull("String_Node_Str" + compiler.toSource(normalizeCheckMainRootClone) + "String_Node_Str"+ compiler.toSource(mainRoot)+ "String_Node_Str"+ explanation,explanation);
    }
  }
 else {
    String errors="String_Node_Str";
    for (    JSError actualError : compiler.getErrors()) {
      errors+=actualError.description + "String_Node_Str";
    }
    assertEquals("String_Node_Str" + errors,1,compiler.getErrorCount());
    assertEquals(errors,error,compiler.getErrors()[0].getType());
    if (warning != null) {
      String warnings="String_Node_Str";
      for (      JSError actualError : compiler.getWarnings()) {
        warnings+=actualError.description + "String_Node_Str";
      }
      assertEquals("String_Node_Str" + warnings,1,compiler.getWarningCount());
      assertEquals(warnings,warning,compiler.getWarnings()[0].getType());
    }
  }
}