|
23 | 23 | import com.google.common.base.Predicate;
|
24 | 24 | import com.google.common.collect.FluentIterable;
|
25 | 25 | import com.google.common.collect.ImmutableList;
|
| 26 | +import com.google.common.collect.ImmutableMap; |
26 | 27 | import com.google.common.collect.ImmutableSet;
|
27 | 28 | import com.google.common.collect.Iterables;
|
28 | 29 | import com.google.common.collect.Lists;
|
| 30 | +import com.google.common.collect.Maps; |
29 | 31 | import com.google.common.io.ByteStreams;
|
30 | 32 | import com.google.testing.compile.Compilation.Result;
|
31 | 33 |
|
|
36 | 38 |
|
37 | 39 | import java.io.IOException;
|
38 | 40 | import java.util.Arrays;
|
| 41 | +import java.util.Map; |
39 | 42 |
|
40 | 43 | import javax.annotation.processing.Processor;
|
41 | 44 | import javax.tools.Diagnostic;
|
@@ -254,38 +257,73 @@ public GeneratedPredicateClause and() {
|
254 | 257 | @Override
|
255 | 258 | public SuccessfulCompilationClause generatesSources(JavaFileObject first,
|
256 | 259 | JavaFileObject... rest) {
|
257 |
| - ImmutableList<JavaFileObject> generatedSources = result.generatedSources(); |
258 |
| - Iterable<? extends CompilationUnitTree> actualCompilationUnits = |
259 |
| - Compilation.parse(generatedSources); |
| 260 | + |
| 261 | + final FluentIterable<? extends CompilationUnitTree> actualTrees = FluentIterable.from( |
| 262 | + Compilation.parse(result.generatedSources())); |
| 263 | + final FluentIterable<? extends CompilationUnitTree> expectedTrees = FluentIterable.from( |
| 264 | + Compilation.parse(Lists.asList(first, rest))); |
260 | 265 | final EqualityScanner scanner = new EqualityScanner();
|
261 |
| - for (final CompilationUnitTree expectedTree : Compilation.parse(Lists.asList(first, rest))) { |
262 |
| - Optional<? extends CompilationUnitTree> found = |
263 |
| - Iterables.tryFind(actualCompilationUnits, new Predicate<CompilationUnitTree>() { |
264 |
| - @Override |
265 |
| - public boolean apply(CompilationUnitTree actualTree) { |
266 |
| - return scanner.visitCompilationUnit(expectedTree, actualTree); |
267 |
| - } |
268 |
| - }); |
269 |
| - if (!found.isPresent()) { |
270 |
| - final JavaFileObject expected = expectedTree.getSourceFile(); |
271 |
| - Optional<JavaFileObject> actual = |
272 |
| - FluentIterable.from(generatedSources).firstMatch(new Predicate<JavaFileObject>() { |
273 |
| - @Override public boolean apply(JavaFileObject generatedFile) { |
274 |
| - return generatedFile.toUri().getPath().endsWith(expected.toUri().getPath()); |
| 266 | + |
| 267 | + Function<? super CompilationUnitTree, ImmutableSet<String>> getTypesFunction = |
| 268 | + new Function<CompilationUnitTree, ImmutableSet<String>>() { |
| 269 | + @Override public ImmutableSet<String> apply(CompilationUnitTree compilationUnit) { |
| 270 | + return TypeScanner.getTopLevelTypes(compilationUnit); |
| 271 | + } |
| 272 | + }; |
| 273 | + |
| 274 | + final ImmutableMap<? extends CompilationUnitTree, ImmutableSet<String>> expectedTreeTypes = |
| 275 | + Maps.toMap(expectedTrees, getTypesFunction); |
| 276 | + final ImmutableMap<? extends CompilationUnitTree, ImmutableSet<String>> actualTreeTypes = |
| 277 | + Maps.toMap(actualTrees, getTypesFunction); |
| 278 | + final ImmutableMap<? extends CompilationUnitTree, Optional<? extends CompilationUnitTree>> |
| 279 | + matchedTrees = Maps.toMap(expectedTrees, |
| 280 | + new Function<CompilationUnitTree, Optional<? extends CompilationUnitTree>>() { |
| 281 | + @Override public Optional<? extends CompilationUnitTree> apply( |
| 282 | + final CompilationUnitTree expectedTree) { |
| 283 | + return Iterables.tryFind(actualTrees, |
| 284 | + new Predicate<CompilationUnitTree>() { |
| 285 | + @Override public boolean apply(CompilationUnitTree actualTree) { |
| 286 | + return expectedTreeTypes.get(expectedTree).equals( |
| 287 | + actualTreeTypes.get(actualTree)); |
| 288 | + } |
| 289 | + }); |
275 | 290 | }
|
276 | 291 | });
|
277 |
| - if (actual.isPresent()) { |
278 |
| - CharSequence actualSource = null; |
279 |
| - try { |
280 |
| - actualSource = actual.get().getCharContent(false); |
281 |
| - } catch (IOException e) { |
282 |
| - throw new RuntimeException("Exception reading source content.", e); |
283 |
| - } |
284 |
| - failureStrategy.fail("Generated file " + expected.getName() |
285 |
| - + " did not match expectation. Found:\n" |
286 |
| - + (actualSource == null ? "no source found" : actualSource)); |
287 |
| - } else { |
288 |
| - failureStrategy.fail("Did not find a source file named " + expected.getName()); |
| 292 | + |
| 293 | + for (Map.Entry<? extends CompilationUnitTree, Optional<? extends CompilationUnitTree>> |
| 294 | + matchedTreePair : matchedTrees.entrySet()) { |
| 295 | + final CompilationUnitTree expectedTree = matchedTreePair.getKey(); |
| 296 | + JavaFileObject expectedSource = expectedTree.getSourceFile(); |
| 297 | + if (!matchedTreePair.getValue().isPresent()) { |
| 298 | + failureStrategy.fail(String.format("None of the sources generated declared the same " |
| 299 | + + "top-level types as the expected source at %s (Types: %s).\n " |
| 300 | + + "Generated files at:\n%s", |
| 301 | + expectedSource.getName(), expectedTreeTypes.get(expectedTree), |
| 302 | + Joiner.on('\n').join( |
| 303 | + actualTrees.transform(new Function<CompilationUnitTree, String>() { |
| 304 | + @Override public String apply(CompilationUnitTree generated) { |
| 305 | + return String.format("%s (Types: %s)", |
| 306 | + generated.getSourceFile().getName(), |
| 307 | + actualTreeTypes.get(generated)); |
| 308 | + } |
| 309 | + }) |
| 310 | + .toList()))); |
| 311 | + } |
| 312 | + |
| 313 | + CompilationUnitTree actualTree = matchedTreePair.getValue().get(); |
| 314 | + JavaFileObject actualSource = actualTree.getSourceFile(); |
| 315 | + |
| 316 | + if (!scanner.visitCompilationUnit(expectedTree, actualTree)) { |
| 317 | + try { |
| 318 | + String expectedContent = expectedSource.getCharContent(false).toString(); |
| 319 | + String actualContent = actualSource.getCharContent(false).toString(); |
| 320 | + failureStrategy.fail(String.format("The source generated at %s declared the same " |
| 321 | + + "top-level types as the expected source at %s, but didn't match exactly. " |
| 322 | + + "Actual:\n\n%s\n\nExpected:\n\n%s", actualSource.getName(), |
| 323 | + expectedSource.getName(), actualContent, expectedContent)); |
| 324 | + } catch (IOException e) { |
| 325 | + throw new IllegalStateException("Couldn't read from JavaFileObject when it was already " |
| 326 | + + "in memory.", e); |
289 | 327 | }
|
290 | 328 | }
|
291 | 329 | }
|
|
0 commit comments