Program: 19475
Project: 19475
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,List<SourceFile> expected,DiagnosticType error,DiagnosticType warning,String description){
  RecentChange recentChange=new RecentChange();
  compiler.addChangeHandler(recentChange);
  Node root=compiler.parseInputs();
  String errorMsg=LINE_JOINER.join(compiler.getErrors());
  if (root == null && expected == null && error != null) {
    assert_().withFailureMessage("String_Node_Str" + errorMsg).that(compiler.getErrorCount()).isEqualTo(1);
    JSError actualError=compiler.getErrors()[0];
    assert_().withFailureMessage("String_Node_Str" + errorMsg).that(actualError.getType()).isEqualTo(error);
    if (description != null) {
      assertThat(actualError.description).isEqualTo(description);
    }
    return;
  }
  assert_().withFailureMessage("String_Node_Str" + errorMsg).that(root).isNotNull();
  if (!expectParseWarningsThisTest) {
    assertEquals("String_Node_Str" + LINE_JOINER.join(compiler.getWarnings()),0,compiler.getWarnings().length);
  }
  if (astValidationEnabled) {
    (new AstValidator(compiler)).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=new ArrayList<>();
  boolean hasCodeChanged=false;
  for (int i=0; i < numRepetitions; ++i) {
    if (compiler.getErrorCount() == 0) {
      errorManagers[i]=new BlackHoleErrorManager();
      compiler.setErrorManager(errorManagers[i]);
      if (rewriteClosureCode && i == 0) {
        new ClosureRewriteClass(compiler).process(null,mainRoot);
        new ClosureRewriteModule(compiler).process(null,mainRoot);
        new ScopedAliases(compiler,null,CompilerOptions.NULL_ALIAS_TRANSFORMATION_HANDLER).process(null,mainRoot);
        hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      }
      if (closurePassEnabled && i == 0) {
        recentChange.reset();
        new ProcessClosurePrimitives(compiler,null,CheckLevel.ERROR,false).process(null,mainRoot);
        hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      }
      if (transpileEnabled && i == 0) {
        recentChange.reset();
        transpileToEs5(compiler,externsRoot,mainRoot);
        hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      }
      if (!runTypeCheckAfterProcessing && typeCheckEnabled && i == 0) {
        TypeCheck check=createTypeCheck(compiler,reportMissingOverrideCheckLevel);
        check.processForTesting(externsRoot,mainRoot);
      }
 else       if (!this.runNTIAfterProcessing && this.newTypeInferenceEnabled && i == 0) {
        runNewTypeInference(compiler,externsRoot,mainRoot);
      }
      if (normalizeEnabled && i == 0) {
        normalizeActualCode(compiler,externsRoot,mainRoot);
      }
      if (enableInferConsts && i == 0) {
        new InferConsts(compiler).process(externsRoot,mainRoot);
      }
      if (computeSideEffects && i == 0) {
        PureFunctionIdentifier.Driver mark=new PureFunctionIdentifier.Driver(compiler,null,false);
        mark.process(externsRoot,mainRoot);
      }
      if (markNoSideEffects && i == 0) {
        MarkNoSideEffectCalls mark=new MarkNoSideEffectCalls(compiler);
        mark.process(externsRoot,mainRoot);
      }
      if (gatherExternPropertiesEnabled && i == 0) {
        (new GatherExternProperties(compiler)).process(externsRoot,mainRoot);
      }
      recentChange.reset();
      getProcessor(compiler).process(externsRoot,mainRoot);
      if (astValidationEnabled) {
        (new AstValidator(compiler)).validateRoot(root);
      }
      if (checkLineNumbers) {
        (new LineNumberCheck(compiler)).process(externsRoot,mainRoot);
      }
      if (runTypeCheckAfterProcessing && typeCheckEnabled && i == 0) {
        TypeCheck check=createTypeCheck(compiler,reportMissingOverrideCheckLevel);
        check.processForTesting(externsRoot,mainRoot);
      }
 else       if (this.runNTIAfterProcessing && this.newTypeInferenceEnabled && i == 0) {
        runNewTypeInference(compiler,externsRoot,mainRoot);
      }
      hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      aggregateWarningCount+=errorManagers[i].getWarningCount();
      Collections.addAll(aggregateWarnings,compiler.getWarnings());
      if (normalizeEnabled) {
        boolean verifyDeclaredConstants=true;
        new Normalize.VerifyConstants(compiler,verifyDeclaredConstants).process(externsRoot,mainRoot);
      }
    }
  }
  if (error == null) {
    assertEquals("String_Node_Str" + LINE_JOINER.join(compiler.getErrors()),0,compiler.getErrorCount());
    ErrorManager symbolTableErrorManager=new BlackHoleErrorManager();
    compiler.setErrorManager(symbolTableErrorManager);
    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);
      assertThat(stErrors[0].getType()).isEqualTo(expectedSymbolTableError);
    }
 else {
      assertEquals("String_Node_Str" + LINE_JOINER.join(stErrors),0,stErrors.length);
    }
    if (warning == null) {
      assertEquals("String_Node_Str" + LINE_JOINER.join(aggregateWarnings),0,aggregateWarningCount);
    }
 else {
      assertEquals("String_Node_Str" + numRepetitions + "String_Node_Str"+ LINE_JOINER.join(aggregateWarnings),numRepetitions,aggregateWarningCount);
      for (int i=0; i < numRepetitions; ++i) {
        JSError[] warnings=errorManagers[i].getWarnings();
        JSError actual=warnings[0];
        assertThat(actual.getType()).isEqualTo(warning);
        validateSourceLocation(actual);
        if (description != null) {
          assertThat(actual.description).isEqualTo(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" + "String_Node_Str" + mainRootClone.toStringTree() + "String_Node_Str"+ mainRoot.toStringTree(),hasCodeChanged);
    }
    NodeUtil.verifyScopeChanges(mtoc,mainRoot,false);
    if (expected != null) {
      if (compareAsTree) {
        String explanation;
        if (compareJsDoc) {
          explanation=expectedRoot.checkTreeEqualsIncludingJsDoc(mainRoot);
        }
 else {
          explanation=expectedRoot.checkTreeEquals(mainRoot);
        }
        if (explanation != null) {
          String expectedAsSource=compiler.toSource(expectedRoot);
          String mainAsSource=compiler.toSource(mainRoot);
          if (expectedAsSource.equals(mainAsSource)) {
            fail("String_Node_Str" + expectedAsSource + "String_Node_Str"+ explanation);
          }
 else {
            fail("String_Node_Str" + expectedAsSource + "String_Node_Str"+ mainAsSource+ "String_Node_Str"+ explanation);
          }
        }
      }
 else       if (expected != null) {
        String[] expectedSources=new String[expected.size()];
        for (int i=0; i < expected.size(); ++i) {
          try {
            expectedSources[i]=expected.get(i).getCode();
          }
 catch (          IOException e) {
            throw new RuntimeException("String_Node_Str",e);
          }
        }
        assertThat(compiler.toSource(mainRoot)).isEqualTo(Joiner.on("String_Node_Str").join(expectedSources));
      }
    }
    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" + "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" + "String_Node_Str" + compiler.toSource(normalizeCheckMainRootClone) + "String_Node_Str"+ compiler.toSource(mainRoot)+ "String_Node_Str"+ explanation,explanation);
    }
  }
 else {
    assertNull("String_Node_Str",expected);
    assertEquals("String_Node_Str" + errorMsg + "String_Node_Str"+ Arrays.toString(compiler.getErrors()),1,compiler.getErrorCount());
    JSError actualError=compiler.getErrors()[0];
    assertEquals(errorMsg,error,actualError.getType());
    validateSourceLocation(actualError);
    if (description != null) {
      assertThat(actualError.description).isEqualTo(description);
    }
    assert_().withFailureMessage("String_Node_Str").that(actualError.description).doesNotContainMatch("String_Node_Str");
    if (warning != null) {
      String warnings="String_Node_Str";
      for (      JSError actualWarning : compiler.getWarnings()) {
        warnings+=actualWarning.description + "String_Node_Str";
        assert_().withFailureMessage("String_Node_Str").that(actualWarning.description).doesNotContainMatch("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,List<SourceFile> expected,DiagnosticType error,DiagnosticType warning,String description){
  RecentChange recentChange=new RecentChange();
  compiler.addChangeHandler(recentChange);
  Node root=compiler.parseInputs();
  String errorMsg=LINE_JOINER.join(compiler.getErrors());
  if (root == null && expected == null && error != null) {
    assert_().withFailureMessage("String_Node_Str" + errorMsg).that(compiler.getErrorCount()).isEqualTo(1);
    JSError actualError=compiler.getErrors()[0];
    assert_().withFailureMessage("String_Node_Str" + errorMsg).that(actualError.getType()).isEqualTo(error);
    if (description != null) {
      assertThat(actualError.description).isEqualTo(description);
    }
    return;
  }
  assert_().withFailureMessage("String_Node_Str" + errorMsg).that(root).isNotNull();
  if (!expectParseWarningsThisTest) {
    assertEquals("String_Node_Str" + LINE_JOINER.join(compiler.getWarnings()),0,compiler.getWarnings().length);
  }
  if (astValidationEnabled) {
    (new AstValidator(compiler)).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=new ArrayList<>();
  boolean hasCodeChanged=false;
  for (int i=0; i < numRepetitions; ++i) {
    if (compiler.getErrorCount() == 0) {
      errorManagers[i]=new BlackHoleErrorManager();
      compiler.setErrorManager(errorManagers[i]);
      if (rewriteClosureCode && i == 0) {
        new ClosureRewriteClass(compiler).process(null,mainRoot);
        new ClosureRewriteModule(compiler).process(null,mainRoot);
        new ScopedAliases(compiler,null,CompilerOptions.NULL_ALIAS_TRANSFORMATION_HANDLER).process(null,mainRoot);
        hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      }
      if (closurePassEnabled && i == 0) {
        recentChange.reset();
        new ProcessClosurePrimitives(compiler,null,CheckLevel.ERROR,false).process(null,mainRoot);
        hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      }
      if (transpileEnabled && i == 0) {
        recentChange.reset();
        transpileToEs5(compiler,externsRoot,mainRoot);
        hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      }
      if (!runTypeCheckAfterProcessing && typeCheckEnabled && i == 0) {
        TypeCheck check=createTypeCheck(compiler,reportMissingOverrideCheckLevel);
        check.processForTesting(externsRoot,mainRoot);
      }
 else       if (!this.runNTIAfterProcessing && this.newTypeInferenceEnabled && i == 0) {
        runNewTypeInference(compiler,externsRoot,mainRoot);
      }
      if (normalizeEnabled && i == 0) {
        normalizeActualCode(compiler,externsRoot,mainRoot);
      }
      if (enableInferConsts && i == 0) {
        new InferConsts(compiler).process(externsRoot,mainRoot);
      }
      if (computeSideEffects && i == 0) {
        PureFunctionIdentifier.Driver mark=new PureFunctionIdentifier.Driver(compiler,null,false);
        mark.process(externsRoot,mainRoot);
      }
      if (markNoSideEffects && i == 0) {
        MarkNoSideEffectCalls mark=new MarkNoSideEffectCalls(compiler);
        mark.process(externsRoot,mainRoot);
      }
      if (gatherExternPropertiesEnabled && i == 0) {
        (new GatherExternProperties(compiler)).process(externsRoot,mainRoot);
      }
      recentChange.reset();
      getProcessor(compiler).process(externsRoot,mainRoot);
      if (astValidationEnabled) {
        (new AstValidator(compiler)).validateRoot(root);
      }
      if (checkLineNumbers) {
        (new LineNumberCheck(compiler)).process(externsRoot,mainRoot);
      }
      if (runTypeCheckAfterProcessing && typeCheckEnabled && i == 0) {
        TypeCheck check=createTypeCheck(compiler,reportMissingOverrideCheckLevel);
        check.processForTesting(externsRoot,mainRoot);
      }
 else       if (this.runNTIAfterProcessing && this.newTypeInferenceEnabled && i == 0) {
        runNewTypeInference(compiler,externsRoot,mainRoot);
      }
      hasCodeChanged=hasCodeChanged || recentChange.hasCodeChanged();
      aggregateWarningCount+=errorManagers[i].getWarningCount();
      Collections.addAll(aggregateWarnings,compiler.getWarnings());
      if (normalizeEnabled) {
        boolean verifyDeclaredConstants=true;
        new Normalize.VerifyConstants(compiler,verifyDeclaredConstants).process(externsRoot,mainRoot);
      }
    }
  }
  if (error == null) {
    assertEquals("String_Node_Str" + LINE_JOINER.join(compiler.getErrors()),0,compiler.getErrorCount());
    ErrorManager symbolTableErrorManager=new BlackHoleErrorManager();
    compiler.setErrorManager(symbolTableErrorManager);
    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);
      assertThat(stErrors[0].getType()).isEqualTo(expectedSymbolTableError);
    }
 else {
      assertEquals("String_Node_Str" + LINE_JOINER.join(stErrors),0,stErrors.length);
    }
    if (warning == null) {
      assertEquals("String_Node_Str" + LINE_JOINER.join(aggregateWarnings),0,aggregateWarningCount);
    }
 else {
      assertEquals("String_Node_Str" + numRepetitions + "String_Node_Str"+ LINE_JOINER.join(aggregateWarnings),numRepetitions,aggregateWarningCount);
      for (int i=0; i < numRepetitions; ++i) {
        JSError[] warnings=errorManagers[i].getWarnings();
        JSError actual=warnings[0];
        assertThat(actual.getType()).isEqualTo(warning);
        validateSourceLocation(actual);
        if (description != null) {
          assertThat(actual.description).isEqualTo(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" + "String_Node_Str" + mainRootClone.toStringTree() + "String_Node_Str"+ mainRoot.toStringTree(),hasCodeChanged);
    }
    NodeUtil.verifyScopeChanges(mtoc,mainRoot,false);
    if (expected != null) {
      if (compareAsTree) {
        String explanation;
        if (compareJsDoc) {
          explanation=expectedRoot.checkTreeEqualsIncludingJsDoc(mainRoot);
        }
 else {
          explanation=expectedRoot.checkTreeEquals(mainRoot);
        }
        if (explanation != null) {
          String expectedAsSource=compiler.toSource(expectedRoot);
          String mainAsSource=compiler.toSource(mainRoot);
          if (expectedAsSource.equals(mainAsSource)) {
            fail("String_Node_Str" + expectedAsSource + "String_Node_Str"+ explanation);
          }
 else {
            fail("String_Node_Str" + expectedAsSource + "String_Node_Str"+ mainAsSource+ "String_Node_Str"+ explanation);
          }
        }
      }
 else       if (expected != null) {
        String[] expectedSources=new String[expected.size()];
        for (int i=0; i < expected.size(); ++i) {
          try {
            expectedSources[i]=expected.get(i).getCode();
          }
 catch (          IOException e) {
            throw new RuntimeException("String_Node_Str",e);
          }
        }
        assertThat(compiler.toSource(mainRoot)).isEqualTo(Joiner.on("String_Node_Str").join(expectedSources));
      }
    }
    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" + "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" + "String_Node_Str" + compiler.toSource(normalizeCheckMainRootClone) + "String_Node_Str"+ compiler.toSource(mainRoot)+ "String_Node_Str"+ explanation,explanation);
    }
  }
 else {
    assertNull("String_Node_Str",expected);
    assertEquals("String_Node_Str" + error.key + "String_Node_Str"+ Arrays.toString(compiler.getErrors()),1,compiler.getErrorCount());
    JSError actualError=compiler.getErrors()[0];
    assertEquals(errorMsg,error,actualError.getType());
    validateSourceLocation(actualError);
    if (description != null) {
      assertThat(actualError.description).isEqualTo(description);
    }
    assert_().withFailureMessage("String_Node_Str").that(actualError.description).doesNotContainMatch("String_Node_Str");
    if (warning != null) {
      String warnings="String_Node_Str";
      for (      JSError actualWarning : compiler.getWarnings()) {
        warnings+=actualWarning.description + "String_Node_Str";
        assert_().withFailureMessage("String_Node_Str").that(actualWarning.description).doesNotContainMatch("String_Node_Str");
      }
      assertEquals("String_Node_Str" + warnings,1,compiler.getWarningCount());
      assertEquals(warnings,warning,compiler.getWarnings()[0].getType());
    }
  }
}