Package com.google.errorprone

Source Code of com.google.errorprone.CompilationTestHelper

/*
* Copyright 2012 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.errorprone;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import com.google.common.collect.ImmutableList;
import com.google.errorprone.bugpatterns.BugChecker;

import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.main.Main.Result;
import com.sun.tools.javac.util.Context;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;

/**
* Utility class for tests that need to build using error-prone.
* @author eaftan@google.com (Eddie Aftandilian)
*
* TODO(user): Refactor default argument construction to make setup cleaner.
*/
public class CompilationTestHelper {

  private static final List<String> DEFAULT_ARGS = ImmutableList.of(
      "-encoding", "UTF-8", "-Xjcov");

  private final DiagnosticTestHelper diagnosticHelper;
  private final ErrorProneCompiler compiler;
  private final ByteArrayOutputStream outputStream;
  private final ErrorProneInMemoryFileManager fileManager = new ErrorProneInMemoryFileManager();

  private CompilationTestHelper(Scanner scanner, String checkName) {
    this.diagnosticHelper = new DiagnosticTestHelper(checkName);
    this.outputStream = new ByteArrayOutputStream();
    this.compiler = new ErrorProneCompiler.Builder().report(scanner)
        .redirectOutputTo(new PrintWriter(outputStream, /*autoFlush=*/true))
        .listenToDiagnostics(diagnosticHelper.collector).build();
  }

  public static CompilationTestHelper newInstance(Scanner scanner) {
    return new CompilationTestHelper(scanner, null);
  }

  public static CompilationTestHelper newInstance(Scanner scanner, String checkName) {
    return new CompilationTestHelper(scanner, checkName);
  }

  /**
   * Test an error-prone {@link BugChecker}.
   */
  public static CompilationTestHelper newInstance(BugChecker checker) {
    Scanner scanner = new ErrorProneScanner(checker);
    String checkName = checker.getCanonicalName();
    return new CompilationTestHelper(scanner, checkName);
  }

  /**
   * Pass -proc:none unless annotation processing is explicitly enabled, to avoid picking up
   * annotation processors via service loading.
   */
  // TODO(user): test compilations should be isolated so they can't pick things up from the
  // ambient classpath.
  static List<String> disableImplicitProcessing(List<String> args) {
    if (args.indexOf("-processor") != -1
        || args.indexOf("-processorpath") != -1) {
      return args;
    }
    return ImmutableList.<String>builder().addAll(args).add("-proc:none").build();
  }

  /**
   * Creates a list of arguments to pass to the compiler, including the list of source files
   * to compile.  Uses DEFAULT_ARGS as the base and appends the extraArgs passed in.
   */
  private static List<String> buildArguments(List<String> extraArgs) {
    return ImmutableList.<String>builder()
        .addAll(DEFAULT_ARGS)
        .addAll(disableImplicitProcessing(extraArgs))
        .build();
  }

  /**
   * Returns the file manager associated with the test compilation.
   */
  public ErrorProneInMemoryFileManager fileManager() {
    return fileManager;
  }

  /**
   * Asserts that the compilation succeeds and no diagnostics were produced.
   *
   * @param sources The list of files to compile
   * @param args Extra command-line arguments to pass to the compiler
   */
  public void assertCompileSucceeds(List<JavaFileObject> sources, List<String> args) {
    List<String> allArgs = buildArguments(args);
    Result exitCode = compile(asJavacList(sources), allArgs.toArray(new String[0]));
    List<Diagnostic<? extends JavaFileObject>> diagnostics = diagnosticHelper.getDiagnostics();
    assertThat("Compilation failed: " + diagnostics.toString(), exitCode, is(Result.OK));
    assertThat("Compilation succeeded but gave warnings: " + diagnostics.toString(),
        diagnostics.size(), is(0));
  }

  /**
   * Asserts that the compilation succeeds and no diagnostics were produced.
   *
   * @param sources The list of files to compile
   */
  public void assertCompileSucceeds(List<JavaFileObject> sources) {
    assertCompileSucceeds(sources, ImmutableList.<String>of());
  }

  /**
   * Asserts that the compilation succeeds and no diagnostics were produced. Convenience method
   * for the common case of one source file and no extra args.
   */
  public void assertCompileSucceeds(JavaFileObject source) {
    assertCompileSucceeds(ImmutableList.of(source));
  }

  /**
   * Assert that the compile succeeds, and that for each line of the test file that contains
   * the pattern "// BUG: Diagnostic contains: foo", the diagnostic at that line contains "foo".
   */
  public void assertCompileSucceedsWithMessages(List<JavaFileObject> sources) throws IOException {
    assertCompileSucceedsIgnoringWarnings(sources);
    for (JavaFileObject source : sources) {
      diagnosticHelper.assertHasDiagnosticOnAllMatchingLines(source);
    }
  }

  /**
   * Asserts that the compile succeeds, and that for each line of the test file that contains
   * the pattern "// BUG: Diagnostic contains: foo", the diagnostic at that line contains "foo".
   * Convenience method for the common case of one source file and no extra args.
   */
  public void assertCompileSucceedsWithMessages(JavaFileObject source) throws IOException {
    assertCompileSucceedsWithMessages(ImmutableList.of(source));
  }

  /**
   * Asserts that the compilation succeeds regardless of whether any diagnostics were produced.
   */
  private void assertCompileSucceedsIgnoringWarnings(List<JavaFileObject> sources) {
    List<String> allArgs = buildArguments(Collections.<String>emptyList());
    Result exitCode = compile(asJavacList(sources), allArgs.toArray(new String[0]));
    assertThat(diagnosticHelper.getDiagnostics().toString(), exitCode, is(Result.OK));
  }

  /**
   * Asserts that the compile fails, and that for each line of the test file that contains
   * the pattern "// BUG: Diagnostic contains: foo", the diagnostic at that line contains "foo".
   *
   * @param sources The list of files to compile
   */
  public void assertCompileFailsWithMessages(List<JavaFileObject> sources) throws IOException {
    assertCompileFailsWithMessages(sources, Collections.<String>emptyList());
  }

  /**
   * Asserts that the compile fails, and that for each line of the test file that contains
   * the pattern "// BUG: Diagnostic contains: foo", the diagnostic at that line contains "foo".
   *
   * @param sources The list of files to compile
   * @param args The list of args to pass to the compilation
   */
  public void assertCompileFailsWithMessages(List<JavaFileObject> sources, List<String> args)
      throws IOException {
    List<String> allArgs = buildArguments(args);
    Result exitCode = compile(asJavacList(sources), allArgs.toArray(new String[0]));
    assertThat("Compiler returned an unexpected error code", exitCode, is(Result.ERROR));
    for (JavaFileObject source : sources) {
      diagnosticHelper.assertHasDiagnosticOnAllMatchingLines(source);
    }
  }

  /**
   * Asserts that the compile fails, and that for each line of the test file that contains
   * the pattern "// BUG: Diagnostic contains: foo", the diagnostic at that line contains "foo".
   * Convenience method for the common case of one source file and no extra args.
   */
  public void assertCompileFailsWithMessages(JavaFileObject source) throws IOException {
    assertCompileFailsWithMessages(ImmutableList.of(source));
  }

  Result compile(Iterable<JavaFileObject> sources, String[] args) {
    checkWellFormed(sources, args);
    Context context = new Context();
    context.put(JavaFileManager.class, fileManager);
    return compiler.compile(args, context, asJavacList(sources), null);
  }

  private void checkWellFormed(Iterable<JavaFileObject> sources, String[] args) {
    JavaCompiler compiler = JavacTool.create();
    OutputStream outputStream = new ByteArrayOutputStream();
    CompilationTask task = compiler.getTask(
        new PrintWriter(outputStream, /*autoFlush=*/true),
        fileManager,
        null,
        buildArguments(Arrays.asList(ErrorProneOptions.processArgs(args).getRemainingArgs())),
        null,
        sources);
    boolean result = task.call();
    assertTrue(String.format("Test program failed to compile with non error-prone error: %s",
        outputStream.toString()), result);
  }

  public static <T> com.sun.tools.javac.util.List<T> asJavacList(Iterable<? extends T> xs) {
    com.sun.tools.javac.util.List<T> result = com.sun.tools.javac.util.List.nil();
    for (T x : xs) {
      result = result.append(x);
    }
    return result;
  }

}
TOP

Related Classes of com.google.errorprone.CompilationTestHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.