aboutsummaryrefslogtreecommitdiff
path: root/value/src/it
diff options
context:
space:
mode:
authorÉamonn McManus <emcmanus@google.com>2021-04-05 08:58:03 -0700
committerGoogle Java Core Libraries <java-libraries-firehose+copybara@google.com>2021-04-05 08:58:36 -0700
commit79d7e9c3d2487227ae1d803465a00ea7f4670b8c (patch)
tree2e9b75c38a1dd12febfdef2f7197175011b02bf8 /value/src/it
parent0076afb3825bd4d3b7ab77310855c2cc4a05813e (diff)
downloadauto-79d7e9c3d2487227ae1d803465a00ea7f4670b8c.tar.gz
Move the AutoBuilder tests for Kotlin data classes to a separate test class.
Unfortunately it appears that JDK versions before 11 have a bug where the compiler won't report parameter names to annotation processors if the parameters are in code that has been compiled separately. This is true even if the code is compiled with `-parameters`. It might not happen always, but it does happen for the Kotlin data classes we are testing against. So we exclude the test that uses them when running with JDK version < 11. Also add a missing `-A` flag that is needed for the `record` compilation test, and only run that test with JDK ≥ 16, where records are no longer a preview feature. RELNOTES=n/a PiperOrigin-RevId: 366807595
Diffstat (limited to 'value/src/it')
-rw-r--r--value/src/it/functional/pom.xml54
-rw-r--r--value/src/it/functional/src/test/java/com/google/auto/value/AutoBuilderKotlinTest.java101
-rw-r--r--value/src/it/functional/src/test/java/com/google/auto/value/AutoBuilderTest.java115
3 files changed, 269 insertions, 1 deletions
diff --git a/value/src/it/functional/pom.xml b/value/src/it/functional/pom.xml
index 3449dd82..b613593a 100644
--- a/value/src/it/functional/pom.xml
+++ b/value/src/it/functional/pom.xml
@@ -32,6 +32,7 @@
<version>HEAD-SNAPSHOT</version>
<name>Auto-Value Functional Integration Test</name>
<properties>
+ <kotlin.version>1.4.32</kotlin.version>
<exclude.tests>this-matches-nothing</exclude.tests>
</properties>
<dependencies>
@@ -105,6 +106,11 @@
<artifactId>escapevelocity</artifactId>
<version>0.9.1</version>
</dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-stdlib</artifactId>
+ <version>${kotlin.version}</version>
+ </dependency>
</dependencies>
<build>
@@ -112,7 +118,39 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
- <version>3.2.0</version>
+ <version>3.2.0</version>
+ </plugin>
+ <plugin>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-maven-plugin</artifactId>
+ <version>${kotlin.version}</version>
+ <executions>
+ <!--
+ The Kotlin configuration here is a bit unusual. JetBrains recommends
+ <https://kotlinlang.org/docs/maven.html#compile-kotlin-and-java-sources>
+ a fairly invasive reconfiguration of the maven-compiler-plugin (which compiles Java)
+ in order to ensure that the Kotlin compiler can run first. In our case, we have just
+ one Kotlin file that a test in Java accesses. So, even though it is in src/test/java,
+ we compile it in the `compile` goal, which means it is available to the Java test sources
+ when they are compiled in the `default-testCompile` goal.
+
+ Currently if you want to use JDK ≥ 16 then you must set
+ JAVA_TOOL_OPTIONS=__illegal-access=permit
+ except the two underscores should be dashes (which XML comments won't allow us to write).
+ This is a bug that will presumably be fixed in a forthcoming version.
+ -->
+ <execution>
+ <id>compile</id>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <sourceDirs>
+ <sourceDir>${project.basedir}/src/test/java</sourceDir>
+ </sourceDirs>
+ </configuration>
+ </execution>
+ </executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -132,6 +170,7 @@
<arg>-Xlint:all</arg>
<arg>-encoding</arg>
<arg>utf8</arg>
+ <arg>-Acom.google.auto.value.AutoBuilderIsUnstable</arg>
</compilerArgs>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
@@ -212,5 +251,18 @@
<test.jvm.flags>--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</test.jvm.flags>
</properties>
</profile>
+ <profile>
+ <!-- Before JDK 11, parameter names from already-compiled classes are not reliably available
+ to the compiler even when they are present in class files. Since our Kotlin test file
+ obviously has to be compiled separately from the Java test that uses it,
+ AutoBuilderKotlinTest doesn't pass on earlier JDK versions. -->
+ <id>exclude-separate-compilation-parameter-names</id>
+ <activation>
+ <jdk>(,11)</jdk>
+ </activation>
+ <properties>
+ <exclude.tests>**/AutoBuilderKotlinTest.java</exclude.tests>
+ </properties>
+ </profile>
</profiles>
</project>
diff --git a/value/src/it/functional/src/test/java/com/google/auto/value/AutoBuilderKotlinTest.java b/value/src/it/functional/src/test/java/com/google/auto/value/AutoBuilderKotlinTest.java
new file mode 100644
index 00000000..7b043964
--- /dev/null
+++ b/value/src/it/functional/src/test/java/com/google/auto/value/AutoBuilderKotlinTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * 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.auto.value;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class AutoBuilderKotlinTest {
+ @AutoBuilder(ofClass = KotlinData.class)
+ abstract static class KotlinDataBuilder {
+ static KotlinDataBuilder builder() {
+ return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataBuilder();
+ }
+ // There's a pesky problem with JavaBeans casing which means that calling a property
+ // AString (with getter getAString()) doesn't work because it doesn't find setAString.
+ abstract KotlinDataBuilder setMyInt(int x);
+
+ abstract KotlinDataBuilder setMyString(String x);
+
+ abstract KotlinData build();
+ }
+
+ @Test
+ public void simpleKotlin() {
+ KotlinData x = KotlinDataBuilder.builder().setMyInt(23).setMyString("skidoo").build();
+ assertThat(x.getMyInt()).isEqualTo(23);
+ assertThat(x.getMyString()).isEqualTo("skidoo");
+ }
+
+ @AutoBuilder(ofClass = KotlinDataWithNullable.class)
+ abstract static class KotlinDataWithNullableBuilder {
+ static KotlinDataWithNullableBuilder builder() {
+ return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataWithNullableBuilder();
+ }
+
+ abstract KotlinDataWithNullableBuilder setMyInt(int x);
+
+ abstract KotlinDataWithNullableBuilder setMyString(String x);
+
+ abstract KotlinDataWithNullable build();
+ }
+
+ @Test
+ public void kotlinWithNullable() {
+ // TODO(b/183005059): this does not work yet.
+ // KotlinDataWithNullable empty = KotlinDataWithNullableBuilder.builder().build();
+ // assertThat(empty.getMyInt()).isNull();
+ // assertThat(empty.getMyString()).isNull();
+
+ KotlinDataWithNullable notEmpty =
+ KotlinDataWithNullableBuilder.builder().setMyString("answer").setMyInt(42).build();
+ assertThat(notEmpty.getMyString()).isEqualTo("answer");
+ assertThat(notEmpty.getMyInt()).isEqualTo(42);
+ }
+
+ @AutoBuilder(ofClass = KotlinDataWithDefaults.class)
+ abstract static class KotlinDataWithDefaultsBuilder {
+ static KotlinDataWithDefaultsBuilder builder() {
+ return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataWithDefaultsBuilder();
+ }
+
+ abstract KotlinDataWithDefaultsBuilder setMyInt(int x);
+
+ abstract KotlinDataWithDefaultsBuilder setMyString(String x);
+
+ abstract KotlinDataWithDefaults build();
+ }
+
+ @Test
+ public void kotlinWithDefaults() {
+ // AutoBuilder doesn't currently try to give the builder the same defaults as the Kotlin class,
+ // but we do at least check that the presence of defaults doesn't throw AutoBuilder off.
+ // When a constructor has default parameters, the Kotlin compiler generates an extra constructor
+ // with two extra parameters: an int bitmask saying which parameters were defaulted, and a
+ // DefaultConstructorMarker parameter to avoid clashing with another constructor that might have
+ // an extra int parameter for some other reason. If AutoBuilder found this constructor it might
+ // be confused, but fortunately the constructor is marked synthetic, and javax.lang.model
+ // doesn't show synthetic elements.
+ KotlinDataWithDefaults x =
+ KotlinDataWithDefaultsBuilder.builder().setMyString("answer").setMyInt(42).build();
+ assertThat(x.getMyString()).isEqualTo("answer");
+ assertThat(x.getMyInt()).isEqualTo(42);
+ }
+}
diff --git a/value/src/it/functional/src/test/java/com/google/auto/value/AutoBuilderTest.java b/value/src/it/functional/src/test/java/com/google/auto/value/AutoBuilderTest.java
new file mode 100644
index 00000000..0debaa2c
--- /dev/null
+++ b/value/src/it/functional/src/test/java/com/google/auto/value/AutoBuilderTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * 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.auto.value;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.MoreObjects;
+import java.util.Objects;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class AutoBuilderTest {
+ static class Simple {
+ private final int anInt;
+ private final String aString;
+
+ Simple(int anInt, String aString) {
+ this.anInt = anInt;
+ this.aString = aString;
+ }
+
+ int anInt() {
+ return anInt;
+ }
+
+ String aString() {
+ return aString;
+ }
+
+ @Override
+ public boolean equals(Object x) {
+ if (x instanceof Simple) {
+ Simple that = (Simple) x;
+ return this.anInt == that.anInt && Objects.equals(this.aString, that.aString);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(anInt, aString);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("anInt", anInt)
+ .add("aString", aString)
+ .toString();
+ }
+
+ static Builder builder() {
+ return new AutoBuilder_AutoBuilderTest_Simple_Builder();
+ }
+
+ @AutoBuilder
+ abstract static class Builder {
+ abstract Builder setAnInt(int x);
+
+ abstract Builder setAString(String x);
+
+ abstract Simple build();
+ }
+ }
+
+ @Test
+ public void simple() {
+ Simple x = Simple.builder().setAnInt(23).setAString("skidoo").build();
+ assertThat(x).isEqualTo(new Simple(23, "skidoo"));
+ }
+
+ @AutoValue
+ abstract static class SimpleAuto {
+ abstract int getFoo();
+
+ abstract String getBar();
+
+ static Builder builder() {
+ return new AutoBuilder_AutoBuilderTest_SimpleAuto_Builder();
+ }
+
+ // There's no particular reason to do this since @AutoValue.Builder works just as well, but
+ // let's check anyway.
+ @AutoBuilder(ofClass = AutoValue_AutoBuilderTest_SimpleAuto.class)
+ abstract static class Builder {
+ abstract Builder setFoo(int x);
+
+ abstract Builder setBar(String x);
+
+ abstract AutoValue_AutoBuilderTest_SimpleAuto build();
+ }
+ }
+
+ @Test
+ public void simpleAuto() {
+ SimpleAuto x = SimpleAuto.builder().setFoo(23).setBar("skidoo").build();
+ assertThat(x.getFoo()).isEqualTo(23);
+ assertThat(x.getBar()).isEqualTo("skidoo");
+ }
+}