Skip to content

Commit

Permalink
Merge pull request #88 from google/moe_writing_branch_from_8867a5afd9…
Browse files Browse the repository at this point in the history
…0e3e12c01a964b073fd8558e029aa9

Merge changes from google.
  • Loading branch information
cgruber committed Feb 19, 2016
2 parents fc2c4ba + 2bce197 commit 51cdab8
Show file tree
Hide file tree
Showing 14 changed files with 995 additions and 202 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: java
install: mvn -U install clean --fail-never --quiet -DskipTests=true -Dinvoker.skip=true
script: mvn verify
install: mvn -B -U install clean --fail-never --quiet -DskipTests=true -Dinvoker.skip=true
script: mvn -B verify

jdk:
- openjdk7
Expand Down
14 changes: 5 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
Contributing
============

If you would like to contribute code to compile-testing you can do so through GitHub
by forking the repository and sending a pull request.
If you would like to contribute code to compile-testing you can do so through
GitHub by forking the repository and sending a pull request.

When submitting code, please make every effort to follow existing conventions
and style in order to keep the code as readable as possible.
and style in order to keep the code as readable as possible.

Where appropriate, please provide unit tests or integration tests. Unit tests
should be JUnit based tests and can use either standard JUnit assertions or
Truth assertions and be added to `<project>/src/test/java`. Changes to
code generation or other build-time behaviour should go into small maven
projects using the `maven-invoker-plugin`. Examples of this are in
`generator/src/it` and can include bean-shell verification scripts and other
facilities provided by `maven-invoker-plugin`.
Truth assertions and be added to `<project>/src/test/java`.

Please make sure your code compiles by running `mvn clean verify` which will
execute both unit and integration test phases. Additionally, consider using
execute both unit and integration test phases. Additionally, consider using
http://travis-ci.org to validate your branches before you even put them into
pull requests. All pull requests will be validated by Travis-ci in any case
and must pass before being merged.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ A library for testing javac compilation with or without annotation processors. S
Latest Release
--------------

The latest release is version `0.6`. Include it as a [Maven](http://maven.apache.org/) dependency with the following snippet:
The latest release is version `0.8`. Include it as a [Maven](http://maven.apache.org/) dependency with the following snippet:

```
<dependency>
<groupId>com.google.testing.compile</groupId>
<artifactId>compile-testing</artifactId>
<version>0.6</version>
<version>0.8</version>
<scope>test</scope>
</dependency>
```
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>16.0.1</version>
<version>18.0</version>
</dependency>
<dependency>
<groupId>com.sun</groupId>
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/com/google/testing/compile/Compilation.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import static javax.tools.JavaFileObject.Kind.SOURCE;

import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
Expand All @@ -32,7 +32,6 @@
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import javax.annotation.processing.Processor;
import javax.tools.Diagnostic;
Expand All @@ -56,7 +55,7 @@ private Compilation() {}
* @throws RuntimeException if compilation fails.
*/
static Result compile(Iterable<? extends Processor> processors,
Set<String> options, Iterable<? extends JavaFileObject> sources) {
Iterable<String> options, Iterable<? extends JavaFileObject> sources) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null) {
throw new IllegalStateException("Java Compiler is not present. "
Expand All @@ -70,7 +69,7 @@ static Result compile(Iterable<? extends Processor> processors,
null, // explicitly use the default because old versions of javac log some output on stderr
fileManager,
diagnosticCollector,
ImmutableSet.copyOf(options),
ImmutableList.copyOf(options),
ImmutableSet.<String>of(),
sources);
task.setProcessors(processors);
Expand Down Expand Up @@ -202,7 +201,7 @@ ImmutableList<JavaFileObject> generatedSources() {

@Override
public String toString() {
return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("successful", successful)
.add("diagnostics", diagnostics)
.toString();
Expand Down
125 changes: 102 additions & 23 deletions src/main/java/com/google/testing/compile/CompileTester.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@

import com.google.common.io.ByteSource;

import java.nio.charset.Charset;

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

/**
* The root of the fluent API for testing the result of compilation.
*
* <p>This interface exists only to faciliate a fluent API and is subject to change. Implementing
* <p>This interface exists only to facilitate a fluent API and is subject to change. Implementing
* this interface is not recommended.
*
* @author Gregory Kick
Expand All @@ -36,82 +38,159 @@ public interface CompileTester {
*/
void parsesAs(JavaFileObject first, JavaFileObject... rest);

/** The clause in the fluent API that tests for successful compilation. */
/** The clause in the fluent API that tests for successful compilation without errors. */
SuccessfulCompilationClause compilesWithoutError();

/**
* The clause in the fluent API that tests for successful compilation without warnings or
* errors.
*/
CleanCompilationClause compilesWithoutWarnings();

/** The clause in the fluent API that tests for unsuccessful compilation. */
UnsuccessfulCompilationClause failsToCompile();

/** The clause in the fluent API that allows for chaining test conditions. */
/**
* The clause in the fluent API that allows for chaining test conditions.
*
* @param T the clause type returned by {@link #and()}
*/
public interface ChainingClause<T> {
T and();
}

/**
* The clause in the fluent API that checks that an error is associated with a particular
* The clause in the fluent API that checks notes in a compilation.
*
* @param T the non-generic clause type implementing this interface
*/
public interface CompilationWithNotesClause<T> {
/**
* Checks that a note exists that contains the given fragment in the
* {@linkplain Diagnostic#getMessage(java.util.Locale) diagnostic message}.
*/
FileClause<T> withNoteContaining(String messageFragment);

/**
* Checks that the total note count in all files matches the given amount. This only counts
* diagnostics of the kind {@link Diagnostic.Kind#NOTE}.
*/
T withNoteCount(int noteCount);
}

/**
* The clause in the fluent API that checks notes and warnings in a compilation.
*
* @param T the non-generic clause type implementing this interface
*/
public interface CompilationWithWarningsClause<T> extends CompilationWithNotesClause<T> {

/**
* Checks that a warning exists that contains the given fragment in the
* {@linkplain Diagnostic#getMessage(java.util.Locale) diagnostic message}.
*/
FileClause<T> withWarningContaining(String messageFragment);

/**
* Checks that the total warning count in all files matches the given amount. This only counts
* diagnostics of the kind {@link Diagnostic.Kind#WARNING}.
*/
T withWarningCount(int warningCount);
}

/**
* The clause in the fluent API that checks that a diagnostic is associated with a particular
* {@link JavaFileObject}.
*
* @param T the clause type returned by {@link ChainingClause#and()}
*/
public interface FileClause extends ChainingClause<UnsuccessfulCompilationClause> {
LineClause in(JavaFileObject file);
public interface FileClause<T> extends ChainingClause<T> {
LineClause<T> in(JavaFileObject file);
}

/**
* The clause in the fluent API that checks that an error is on a particular
* The clause in the fluent API that checks that a diagnostic is on a particular
* {@linkplain Diagnostic#getLineNumber() line}.
*
* @param T the clause type returned by {@link ChainingClause#and()}
*/
public interface LineClause extends ChainingClause<UnsuccessfulCompilationClause> {
ColumnClause onLine(long lineNumber);
public interface LineClause<T> extends ChainingClause<T> {
ColumnClause<T> onLine(long lineNumber);
}

/**
* The clause in the fluent API that checks that an error starts at a particular
* The clause in the fluent API that checks that a diagnostic starts at a particular
* {@linkplain Diagnostic#getColumnNumber() column}.
*
* @param T the clause type returned by {@link ChainingClause#and()}
*/
public interface ColumnClause extends ChainingClause<UnsuccessfulCompilationClause> {
ChainingClause<UnsuccessfulCompilationClause> atColumn(long columnNumber);
public interface ColumnClause<T> extends ChainingClause<T> {
ChainingClause<T> atColumn(long columnNumber);
}

/** The clause in the fluent API that checks that files were generated. */
public interface GeneratedPredicateClause {
/**
* The clause in the fluent API that checks that files were generated.
*
* @param T the non-generic clause type implementing this interface
*/
public interface GeneratedPredicateClause<T> {
/**
* Checks that a source file with an equivalent
* <a href="http://en.wikipedia.org/wiki/Abstract_syntax_tree">AST</a> was generated for each of
* the given {@linkplain JavaFileObject files}.
*/
SuccessfulCompilationClause generatesSources(JavaFileObject first, JavaFileObject... rest);
T generatesSources(JavaFileObject first, JavaFileObject... rest);

/**
* Checks that a file with equivalent kind and content was generated for each of the given
* {@linkplain JavaFileObject files}.
*/
SuccessfulCompilationClause generatesFiles(JavaFileObject first, JavaFileObject... rest);
T generatesFiles(JavaFileObject first, JavaFileObject... rest);

/**
* Checks that a file with the specified location, package, and filename was generated.
*/
SuccessfulFileClause generatesFileNamed(
SuccessfulFileClause<T> generatesFileNamed(
JavaFileManager.Location location, String packageName, String relativeName);
}

/** The clause in the fluent API that checks that a generated file has the specified contents. */
public interface SuccessfulFileClause extends ChainingClause<GeneratedPredicateClause> {
/**
* The clause in the fluent API that checks that a generated file has the specified contents.
*
* @param T the non-generic clause type implementing this interface
*/
public interface SuccessfulFileClause<T> extends ChainingClause<GeneratedPredicateClause<T>> {
/**
* Checks that the contents of the generated file match the contents of the specified
* {@link ByteSource}.
*/
SuccessfulFileClause withContents(ByteSource expectedByteSource);
SuccessfulFileClause<T> withContents(ByteSource expectedByteSource);

/**
* Checks that the contents of the generated file are equal to the specified string in the given
* charset.
*/
SuccessfulFileClause<T> withStringContents(Charset charset, String expectedString);
}

/** The clause in the fluent API for further tests on successful compilations. */
public interface SuccessfulCompilationClause extends ChainingClause<GeneratedPredicateClause> {}
public interface SuccessfulCompilationClause
extends CompilationWithWarningsClause<SuccessfulCompilationClause>,
ChainingClause<GeneratedPredicateClause<SuccessfulCompilationClause>> {}

/** The clause in the fluent API for further tests on successful compilations without warnings. */
public interface CleanCompilationClause
extends CompilationWithNotesClause<CleanCompilationClause>,
ChainingClause<GeneratedPredicateClause<CleanCompilationClause>> {}

/** The clause in the fluent API for further tests on unsuccessful compilations. */
public interface UnsuccessfulCompilationClause {
public interface UnsuccessfulCompilationClause
extends CompilationWithWarningsClause<UnsuccessfulCompilationClause> {
/**
* Checks that an error exists that contains the given fragment in the
* {@linkplain Diagnostic#getMessage(java.util.Locale) diagnostic message}.
*/
FileClause withErrorContaining(String messageFragment);
FileClause<UnsuccessfulCompilationClause> withErrorContaining(String messageFragment);

/**
* Checks that the total error count in all files matches the given amount. This only counts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
*/
package com.google.testing.compile;

import com.google.common.base.CharMatcher;
import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteSource;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
Expand All @@ -35,15 +44,6 @@
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardLocation;

import com.google.common.base.CharMatcher;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteSource;

/**
* A file manager implementation that stores all output in memory.
*
Expand Down Expand Up @@ -77,15 +77,11 @@ private static URI uriForJavaFileObject(Location location, String className, Kin

@Override
public boolean isSameFile(FileObject a, FileObject b) {
if (a instanceof InMemoryJavaFileObject) {
if (b instanceof InMemoryJavaFileObject) {
return ((InMemoryJavaFileObject) a).toUri().equals(((InMemoryJavaFileObject) b).toUri());
}
}
if (b instanceof InMemoryJavaFileObject) {
return false;
}
return super.isSameFile(a, b);
/* This check is less strict than what is typically done by the normal compiler file managers
* (e.g. JavacFileManager), but is actually the moral equivalent of what most of the
* implementations do anyway. We use this check rather than just delegating to the compiler's
* file manager because file objects for tests generally cause IllegalArgumentExceptions. */
return a.toUri().equals(b.toUri());
}

@Override
Expand Down Expand Up @@ -214,7 +210,7 @@ public boolean delete() {

@Override
public String toString() {
return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("uri", toUri())
.add("kind", kind)
.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,13 @@ private JavaFileObjects() { }
* source and compilation errors may result if they do not match.
*/
public static JavaFileObject forSourceString(String fullyQualifiedName, String source) {
return new StringSourceJavaFileObject(checkNotNull(fullyQualifiedName), checkNotNull(source));
checkNotNull(fullyQualifiedName);
if (fullyQualifiedName.startsWith("package ")) {
throw new IllegalArgumentException(
String.format("fullyQualifiedName starts with \"package\" (%s). Did you forget to "
+ "specify the name and specify just the source text?", fullyQualifiedName));
}
return new StringSourceJavaFileObject(fullyQualifiedName, checkNotNull(source));
}

private static final Joiner LINE_JOINER = Joiner.on('\n');
Expand Down
Loading

0 comments on commit 51cdab8

Please sign in to comment.