1 /* 2 * Copyright 2021 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.auto.value; 17 18 import static com.google.common.truth.Truth.assertThat; 19 import static org.junit.Assert.assertThrows; 20 21 import com.google.common.collect.ImmutableList; 22 import java.util.List; 23 import org.junit.Test; 24 import org.junit.runner.RunWith; 25 import org.junit.runners.JUnit4; 26 27 @RunWith(JUnit4.class) 28 public final class AutoBuilderKotlinTest { 29 @AutoBuilder(ofClass = KotlinData.class) 30 abstract static class KotlinDataBuilder { builder()31 static KotlinDataBuilder builder() { 32 return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataBuilder(); 33 } 34 builder(KotlinData kotlinData)35 static KotlinDataBuilder builder(KotlinData kotlinData) { 36 return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataBuilder(kotlinData); 37 } 38 setInt(int x)39 abstract KotlinDataBuilder setInt(int x); 40 setString(String x)41 abstract KotlinDataBuilder setString(String x); 42 build()43 abstract KotlinData build(); 44 } 45 46 @Test simpleKotlin()47 public void simpleKotlin() { 48 KotlinData x = KotlinDataBuilder.builder().setInt(23).setString("skidoo").build(); 49 assertThat(x.getInt()).isEqualTo(23); 50 assertThat(x.getString()).isEqualTo("skidoo"); 51 52 KotlinData y = KotlinDataBuilder.builder(x).setString("chromosomes").build(); 53 assertThat(y.getInt()).isEqualTo(23); 54 assertThat(y.getString()).isEqualTo("chromosomes"); 55 56 assertThrows(IllegalStateException.class, () -> KotlinDataBuilder.builder().build()); 57 } 58 59 @AutoBuilder(ofClass = KotlinDataWithNullable.class) 60 abstract static class KotlinDataWithNullableBuilder { builder()61 static KotlinDataWithNullableBuilder builder() { 62 return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataWithNullableBuilder(); 63 } 64 setAnInt(int x)65 abstract KotlinDataWithNullableBuilder setAnInt(int x); 66 setAString(String x)67 abstract KotlinDataWithNullableBuilder setAString(String x); 68 build()69 abstract KotlinDataWithNullable build(); 70 } 71 72 @Test kotlinWithNullable()73 public void kotlinWithNullable() { 74 KotlinDataWithNullable empty = KotlinDataWithNullableBuilder.builder().build(); 75 assertThat(empty.getAnInt()).isNull(); 76 assertThat(empty.getAString()).isNull(); 77 78 KotlinDataWithNullable notEmpty = 79 KotlinDataWithNullableBuilder.builder().setAString("answer").setAnInt(42).build(); 80 assertThat(notEmpty.getAString()).isEqualTo("answer"); 81 assertThat(notEmpty.getAnInt()).isEqualTo(42); 82 } 83 84 @AutoBuilder(ofClass = KotlinDataWithDefaults.class) 85 abstract static class KotlinDataWithDefaultsBuilder { builder()86 static KotlinDataWithDefaultsBuilder builder() { 87 return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataWithDefaultsBuilder(); 88 } 89 setAnInt(int x)90 abstract KotlinDataWithDefaultsBuilder setAnInt(int x); 91 getAnInt()92 abstract int getAnInt(); 93 anImmutableListBuilder()94 abstract ImmutableList.Builder<String> anImmutableListBuilder(); 95 setNotDefaulted(long x)96 abstract KotlinDataWithDefaultsBuilder setNotDefaulted(long x); 97 getNotDefaulted()98 abstract long getNotDefaulted(); 99 setAString(String x)100 abstract KotlinDataWithDefaultsBuilder setAString(String x); 101 getAString()102 abstract String getAString(); 103 build()104 abstract KotlinDataWithDefaults build(); 105 } 106 107 @Test kotlinWithDefaults_explicit()108 public void kotlinWithDefaults_explicit() { 109 KotlinDataWithDefaultsBuilder builder = 110 KotlinDataWithDefaultsBuilder.builder() 111 .setAString("answer") 112 .setNotDefaulted(100L) 113 .setAnInt(42); 114 builder.anImmutableListBuilder().add("bar"); 115 KotlinDataWithDefaults x = builder.build(); 116 assertThat(x.getAString()).isEqualTo("answer"); 117 assertThat(x.getAnImmutableList()).containsExactly("bar"); 118 assertThat(x.getNotDefaulted()).isEqualTo(100L); 119 assertThat(x.getAnInt()).isEqualTo(42); 120 } 121 122 @Test kotlinWithDefaults_defaulted()123 public void kotlinWithDefaults_defaulted() { 124 KotlinDataWithDefaults x = 125 KotlinDataWithDefaultsBuilder.builder().setNotDefaulted(100L).build(); 126 assertThat(x.getAnInt()).isEqualTo(23); 127 assertThat(x.getAnImmutableList()).containsExactly("foo"); 128 assertThat(x.getAString()).isEqualTo("skidoo"); 129 assertThat(x.getNotDefaulted()).isEqualTo(100L); 130 KotlinDataWithDefaults copy = 131 new AutoBuilder_AutoBuilderKotlinTest_KotlinDataWithDefaultsBuilder(x).build(); 132 assertThat(copy).isEqualTo(x); 133 assertThat(copy).isNotSameInstanceAs(x); 134 KotlinDataWithDefaults modified = 135 new AutoBuilder_AutoBuilderKotlinTest_KotlinDataWithDefaultsBuilder(x).setAnInt(17).build(); 136 assertThat(modified.getAnInt()).isEqualTo(17); 137 } 138 139 @Test kotlinWithDefaults_getter()140 public void kotlinWithDefaults_getter() { 141 KotlinDataWithDefaultsBuilder builder = KotlinDataWithDefaultsBuilder.builder(); 142 assertThrows(IllegalStateException.class, builder::getAnInt); 143 builder.setAnInt(42); 144 assertThat(builder.getAnInt()).isEqualTo(42); 145 assertThrows(IllegalStateException.class, builder::getNotDefaulted); 146 builder.setNotDefaulted(100L); 147 assertThat(builder.getNotDefaulted()).isEqualTo(100L); 148 assertThrows(IllegalStateException.class, builder::getAString); 149 builder.setAString("answer"); 150 assertThat(builder.getAString()).isEqualTo("answer"); 151 } 152 153 @AutoBuilder(ofClass = KotlinDataEightDefaults.class) 154 interface KotlinDataEightDefaultsBuilder { builder()155 static KotlinDataEightDefaultsBuilder builder() { 156 return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataEightDefaultsBuilder(); 157 } 158 a1(int x)159 KotlinDataEightDefaultsBuilder a1(int x); 160 a2(int x)161 KotlinDataEightDefaultsBuilder a2(int x); 162 a3(int x)163 KotlinDataEightDefaultsBuilder a3(int x); 164 a4(int x)165 KotlinDataEightDefaultsBuilder a4(int x); 166 a5(int x)167 KotlinDataEightDefaultsBuilder a5(int x); 168 a6(int x)169 KotlinDataEightDefaultsBuilder a6(int x); 170 a7(int x)171 KotlinDataEightDefaultsBuilder a7(int x); 172 a8(int x)173 KotlinDataEightDefaultsBuilder a8(int x); 174 build()175 KotlinDataEightDefaults build(); 176 } 177 178 // We test a class that has exactly 8 default parameters because we will use a byte for the 179 // bitmask in that case and it is possible that we might have an issue with sign extension when 180 // bit 7 of that bitmask is set. 181 @Test kotlinEightDefaults()182 public void kotlinEightDefaults() { 183 KotlinDataEightDefaults allDefaulted = KotlinDataEightDefaultsBuilder.builder().build(); 184 assertThat(allDefaulted.getA1()).isEqualTo(1); 185 assertThat(allDefaulted.getA8()).isEqualTo(8); 186 KotlinDataEightDefaults noneDefaulted = 187 KotlinDataEightDefaultsBuilder.builder() 188 .a1(-1) 189 .a2(-2) 190 .a3(-3) 191 .a4(-4) 192 .a5(-5) 193 .a6(-6) 194 .a7(-7) 195 .a8(-8) 196 .build(); 197 assertThat(noneDefaulted.getA1()).isEqualTo(-1); 198 assertThat(noneDefaulted.getA8()).isEqualTo(-8); 199 } 200 201 @AutoBuilder(ofClass = KotlinDataSomeDefaults.class) 202 interface KotlinDataSomeDefaultsBuilder { builder()203 static KotlinDataSomeDefaultsBuilder builder() { 204 return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataSomeDefaultsBuilder(); 205 } 206 fromInstance(KotlinDataSomeDefaults instance)207 static KotlinDataSomeDefaultsBuilder fromInstance(KotlinDataSomeDefaults instance) { 208 return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataSomeDefaultsBuilder(instance); 209 } 210 requiredInt(int x)211 KotlinDataSomeDefaultsBuilder requiredInt(int x); 212 requiredString(String x)213 KotlinDataSomeDefaultsBuilder requiredString(String x); 214 optionalInt(int x)215 KotlinDataSomeDefaultsBuilder optionalInt(int x); 216 optionalString(String x)217 KotlinDataSomeDefaultsBuilder optionalString(String x); 218 build()219 KotlinDataSomeDefaults build(); 220 } 221 222 @Test kotlinSomeDefaults_someDefaulted()223 public void kotlinSomeDefaults_someDefaulted() { 224 KotlinDataSomeDefaults someDefaulted = 225 KotlinDataSomeDefaultsBuilder.builder().requiredInt(12).requiredString("Monkeys").build(); 226 assertThat(someDefaulted.getOptionalInt()).isEqualTo(23); 227 assertThat(someDefaulted.getOptionalString()).isEqualTo("Skidoo"); 228 assertThat(KotlinDataSomeDefaultsBuilder.fromInstance(someDefaulted).build()) 229 .isEqualTo(someDefaulted); 230 } 231 232 @Test kotlinSomeDefaults_noneDefaulted()233 public void kotlinSomeDefaults_noneDefaulted() { 234 KotlinDataSomeDefaults noneDefaulted = 235 KotlinDataSomeDefaultsBuilder.builder() 236 .requiredInt(12) 237 .requiredString("Monkeys") 238 .optionalInt(3) 239 .optionalString("Oranges") 240 .build(); 241 KotlinDataSomeDefaults copy = KotlinDataSomeDefaultsBuilder.fromInstance(noneDefaulted).build(); 242 assertThat(copy).isEqualTo(noneDefaulted); 243 } 244 245 @Test kotlinSomeDefaults_missingRequired()246 public void kotlinSomeDefaults_missingRequired() { 247 IllegalStateException e = 248 assertThrows( 249 IllegalStateException.class, () -> KotlinDataSomeDefaultsBuilder.builder().build()); 250 assertThat(e).hasMessageThat().contains("requiredInt"); 251 assertThat(e).hasMessageThat().contains("requiredString"); 252 } 253 254 @AutoBuilder(ofClass = KotlinDataWithList.class) 255 interface KotlinDataWithListBuilder { builder()256 static KotlinDataWithListBuilder builder() { 257 return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataWithListBuilder(); 258 } 259 builder(KotlinDataWithList kotlinData)260 static KotlinDataWithListBuilder builder(KotlinDataWithList kotlinData) { 261 return new AutoBuilder_AutoBuilderKotlinTest_KotlinDataWithListBuilder(kotlinData); 262 } 263 list(List<? extends CharSequence> list)264 KotlinDataWithListBuilder list(List<? extends CharSequence> list); 265 number(int number)266 KotlinDataWithListBuilder number(int number); 267 build()268 KotlinDataWithList build(); 269 } 270 271 // The `getList()` method returns `List<CharSequence>` as seen from Java, but the `list` parameter 272 // to the constructor has type `List<? extends CharSequence>`. 273 @Test kotlinWildcards()274 public void kotlinWildcards() { 275 List<String> strings = ImmutableList.of("foo"); 276 KotlinDataWithList x = KotlinDataWithListBuilder.builder().list(strings).number(17).build(); 277 assertThat(x.getList()).isEqualTo(strings); 278 assertThat(x.getNumber()).isEqualTo(17); 279 KotlinDataWithList y = KotlinDataWithListBuilder.builder(x).number(23).build(); 280 assertThat(y.getList()).isEqualTo(strings); 281 assertThat(y.getNumber()).isEqualTo(23); 282 } 283 } 284