blob: 6b7a7725bc8565b6508dfe17bd4025237d7327a7 [file] [log] [blame]
package org.robolectric.annotation.processing;
import static com.google.common.truth.Truth.assertAbout;
import static com.google.common.truth.Truth.assertThat;
import static com.google.testing.compile.JavaFileObjects.forResource;
import static com.google.testing.compile.JavaFileObjects.forSourceString;
import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.robolectric.annotation.processing.RobolectricProcessor.PACKAGE_OPT;
import static org.robolectric.annotation.processing.RobolectricProcessor.SHOULD_INSTRUMENT_PKG_OPT;
import static org.robolectric.annotation.processing.validator.Utils.ROBO_SOURCE;
import static org.robolectric.annotation.processing.validator.Utils.SHADOW_EXTRACTOR_SOURCE;
import static org.robolectric.annotation.processing.validator.Utils.SHADOW_PROVIDER_SOURCE;
import com.google.common.collect.ImmutableList;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class RobolectricProcessorTest {
public static final Map<String,String> DEFAULT_OPTS = new HashMap<String, String>() {{
put(PACKAGE_OPT, "org.robolectric");
}};
@Test
public void robolectricProcessor_supportsPackageOption() {
assertThat(new RobolectricProcessor(DEFAULT_OPTS).getSupportedOptions()).contains(PACKAGE_OPT);
}
@Test
public void robolectricProcessor_supportsShouldInstrumentPackageOption() {
assertThat(
new RobolectricProcessor(DEFAULT_OPTS).getSupportedOptions()).contains(SHOULD_INSTRUMENT_PKG_OPT);
}
@Test
public void unannotatedSource_shouldCompile() {
assertAbout(javaSources())
.that(ImmutableList.of(
ROBO_SOURCE,
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forSourceString("HelloWorld", "final class HelloWorld {}")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.compilesWithoutError();
//.and().generatesNoSources(); Should add this assertion onces
// it becomes available in compile-testing
}
@Test
public void generatedFile_shouldHandleInnerClassCollisions() {
// Because the Generated annotation has a retention of "source", it can't
// be tested by a unit test - must run a source-level test.
assertAbout(javaSources())
.that(ImmutableList.of(
ROBO_SOURCE,
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/ShadowDummy.java"),
forResource("org/robolectric/annotation/processing/shadows/ShadowOuterDummy.java"),
forResource("org/robolectric/annotation/processing/shadows/ShadowUniqueDummy.java")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.compilesWithoutError()
.and()
.generatesSources(forResource("org/robolectric/Robolectric_InnerClassCollision.java"));
}
@Test
public void generatedFile_shouldSkipNonPublicClasses() {
assertAbout(javaSources())
.that(ImmutableList.of(
ROBO_SOURCE,
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/ShadowPrivate.java"),
forResource("org/robolectric/annotation/processing/shadows/ShadowOuterDummy2.java"),
forResource("org/robolectric/annotation/processing/shadows/ShadowDummy.java")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.compilesWithoutError()
.and()
.generatesSources(forResource("org/robolectric/Robolectric_HiddenClasses.java"));
}
@Test
public void generatedFile_shouldHandleAnythingShadows() {
assertAbout(javaSources())
.that(ImmutableList.of(
ROBO_SOURCE,
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/ShadowAnything.java"),
forResource("org/robolectric/annotation/processing/shadows/ShadowDummy.java")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.compilesWithoutError()
.and()
.generatesSources(forResource("org/robolectric/Robolectric_Anything.java"));
}
@Test
public void generatedFile_shouldHandleClassNameOnlyShadows() {
assertAbout(javaSources())
.that(ImmutableList.of(
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/ShadowClassNameOnly.java"),
forResource("org/robolectric/annotation/processing/shadows/ShadowDummy.java")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.compilesWithoutError()
.and()
.generatesSources(forResource("org/robolectric/Robolectric_ClassNameOnly.java"));
}
@Test
public void generatedFile_shouldNotGenerateShadowOfMethodsForExcludedClasses() {
assertAbout(javaSources())
.that(ImmutableList.of(
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/ShadowExcludedFromAndroidSdk.java")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.compilesWithoutError()
.and()
.generatesSources(forResource("org/robolectric/Robolectric_NoExcludedTypes.java"));
}
@Test
public void generatedFile_shouldUseSpecifiedPackage() throws IOException {
StringBuilder expected = new StringBuilder();
InputStream in = RobolectricProcessorTest.class.getClassLoader()
.getResourceAsStream("org/robolectric/Robolectric_ClassNameOnly.java");
BufferedReader reader = new BufferedReader(new InputStreamReader(in, UTF_8));
String line;
while ((line = reader.readLine()) != null) {
expected.append(line).append("\n");
}
line = expected.toString();
line = line.replace("package org.robolectric", "package my.test.pkg");
Map<String,String> opts = new HashMap<>();
opts.put(PACKAGE_OPT, "my.test.pkg");
assertAbout(javaSources())
.that(ImmutableList.of(
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/ShadowClassNameOnly.java"),
forResource("org/robolectric/annotation/processing/shadows/ShadowDummy.java")))
.processedWith(new RobolectricProcessor(opts))
.compilesWithoutError()
.and()
.generatesSources(forSourceString("Shadows", line));
}
@Test
public void shouldGenerateMetaInfServicesFile() {
assertAbout(javaSources())
.that(ImmutableList.of(
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/ShadowClassNameOnly.java"),
forResource("org/robolectric/annotation/processing/shadows/ShadowDummy.java")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.compilesWithoutError()
.and()
.generatesFiles(forResource("META-INF/services/org.robolectric.internal.ShadowProvider"));
}
@Test
public void shouldGracefullyHandleUnrecognisedAnnotation() {
assertAbout(javaSources())
.that(ImmutableList.of(
ROBO_SOURCE,
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/TestWithUnrecognizedAnnotation.java")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.compilesWithoutError();
}
@Test
public void shouldGracefullyHandleNoAnythingClass_withNoRealObject() {
assertAbout(javaSource())
.that(forResource("org/robolectric/annotation/processing/shadows/ShadowAnything.java"))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.failsToCompile();
}
@Test
public void shouldGracefullyHandleNoAnythingClass_withFoundOnImplementsAnnotation() {
assertAbout(javaSources())
.that(ImmutableList.of(
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/ShadowRealObjectWithCorrectAnything.java")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.failsToCompile();
}
@Test
public void shouldGenerateGenericShadowOf() {
assertAbout(javaSources())
.that(ImmutableList.of(
ROBO_SOURCE,
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/ShadowDummy.java"),
forResource("org/robolectric/annotation/processing/shadows/ShadowParameterizedDummy.java")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.compilesWithoutError()
.and()
.generatesSources(forResource("org/robolectric/Robolectric_Parameterized.java"));
}
@Test
public void generatedShadowProvider_canConfigureInstrumentingPackages() {
Map<String, String> options = new HashMap<>();
options.put(PACKAGE_OPT, "org.robolectric");
options.put(SHOULD_INSTRUMENT_PKG_OPT, "false");
assertAbout(javaSources())
.that(ImmutableList.of(
ROBO_SOURCE,
SHADOW_PROVIDER_SOURCE,
SHADOW_EXTRACTOR_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/ShadowAnything.java"),
forResource("org/robolectric/annotation/processing/shadows/ShadowDummy.java")))
.processedWith(new RobolectricProcessor(options))
.compilesWithoutError()
.and()
.generatesSources(forResource("org/robolectric/Robolectric_EmptyProvidedPackageNames.java"));
}
@Test
public void shouldGenerateJavadocJson() throws Exception {
assertAbout(javaSources())
.that(ImmutableList.of(
ROBO_SOURCE,
forResource("org/robolectric/annotation/processing/shadows/DocumentedObjectShadow.java")))
.processedWith(new RobolectricProcessor(DEFAULT_OPTS))
.compilesWithoutError();
JsonParser jsonParser = new JsonParser();
String jsonFile = "build/docs/json/org.robolectric.Robolectric.DocumentedObject.json";
JsonElement json = jsonParser.parse(Files.newBufferedReader(Paths.get(jsonFile), UTF_8));
assertThat(((JsonObject) json).get("documentation").getAsString())
.isEqualTo("Robolectric Javadoc goes here!\n");
// must list imported classes, including inner classes...
assertThat(((JsonObject) json).get("imports").getAsJsonArray())
.containsExactly(
new JsonPrimitive("org.robolectric.Robolectric"),
new JsonPrimitive("org.robolectric.annotation.Implementation"),
new JsonPrimitive("org.robolectric.annotation.Implements"),
new JsonPrimitive("org.robolectric.annotation.Resetter"),
new JsonPrimitive("java.util.Map"),
new JsonPrimitive("org.robolectric.annotation.processing.shadows.DocumentedObjectShadow.SomeEnum")
);
}
}