1 /* 2 * Copyright (C) 2012 The Guava Authors 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 17 package com.google.common.reflect; 18 19 import com.google.common.collect.ImmutableList; 20 import com.google.common.collect.Iterables; 21 import com.google.common.testing.EqualsTester; 22 import com.google.common.testing.NullPointerTester; 23 24 import junit.framework.TestCase; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.lang.reflect.Constructor; 29 import java.lang.reflect.Method; 30 import java.lang.reflect.ParameterizedType; 31 import java.lang.reflect.TypeVariable; 32 import java.util.Collections; 33 34 import javax.annotation.Nullable; 35 36 /** 37 * Unit tests for {@link Invokable}. 38 * 39 * @author Ben Yu 40 */ 41 public class InvokableTest extends TestCase { 42 testConstructor_returnType()43 public void testConstructor_returnType() throws Exception { 44 assertEquals(Prepender.class, 45 Prepender.constructor().getReturnType().getType()); 46 } 47 48 private static class WithConstructorAndTypeParameter<T> { 49 @SuppressWarnings("unused") // by reflection WithConstructorAndTypeParameter()50 <X> WithConstructorAndTypeParameter() {} 51 } 52 testConstructor_returnType_hasTypeParameter()53 public void testConstructor_returnType_hasTypeParameter() throws Exception { 54 @SuppressWarnings("rawtypes") // Foo.class for Foo<T> is always raw type 55 Class<WithConstructorAndTypeParameter> type = WithConstructorAndTypeParameter.class; 56 @SuppressWarnings("rawtypes") // Foo.class 57 Constructor<WithConstructorAndTypeParameter> constructor = type.getDeclaredConstructor(); 58 Invokable<?, ?> factory = Invokable.from(constructor); 59 assertEquals(2, factory.getTypeParameters().length); 60 assertEquals(type.getTypeParameters()[0], factory.getTypeParameters()[0]); 61 assertEquals(constructor.getTypeParameters()[0], factory.getTypeParameters()[1]); 62 ParameterizedType returnType = (ParameterizedType) factory.getReturnType().getType(); 63 assertEquals(type, returnType.getRawType()); 64 assertEquals(ImmutableList.copyOf(type.getTypeParameters()), 65 ImmutableList.copyOf(returnType.getActualTypeArguments())); 66 } 67 testConstructor_exceptionTypes()68 public void testConstructor_exceptionTypes() throws Exception { 69 assertEquals(ImmutableList.of(TypeToken.of(NullPointerException.class)), 70 Prepender.constructor(String.class, int.class).getExceptionTypes()); 71 } 72 testConstructor_typeParameters()73 public void testConstructor_typeParameters() throws Exception { 74 TypeVariable<?>[] variables = 75 Prepender.constructor().getTypeParameters(); 76 assertEquals(1, variables.length); 77 assertEquals("A", variables[0].getName()); 78 } 79 testConstructor_parameters()80 public void testConstructor_parameters() throws Exception { 81 Invokable<?, Prepender> delegate = Prepender.constructor(String.class, int.class); 82 ImmutableList<Parameter> parameters = delegate.getParameters(); 83 assertEquals(2, parameters.size()); 84 assertEquals(String.class, parameters.get(0).getType().getType()); 85 assertTrue(parameters.get(0).isAnnotationPresent(NotBlank.class)); 86 assertEquals(int.class, parameters.get(1).getType().getType()); 87 assertFalse(parameters.get(1).isAnnotationPresent(NotBlank.class)); 88 new EqualsTester() 89 .addEqualityGroup(parameters.get(0)) 90 .addEqualityGroup(parameters.get(1)) 91 .testEquals(); 92 } 93 testConstructor_call()94 public void testConstructor_call() throws Exception { 95 Invokable<?, Prepender> delegate = Prepender.constructor(String.class, int.class); 96 Prepender prepender = delegate.invoke(null, "a", 1); 97 assertEquals("a", prepender.prefix); 98 assertEquals(1, prepender.times); 99 } 100 testConstructor_returning()101 public void testConstructor_returning() throws Exception { 102 Invokable<?, Prepender> delegate = Prepender.constructor(String.class, int.class) 103 .returning(Prepender.class); 104 Prepender prepender = delegate.invoke(null, "a", 1); 105 assertEquals("a", prepender.prefix); 106 assertEquals(1, prepender.times); 107 } 108 testConstructor_invalidReturning()109 public void testConstructor_invalidReturning() throws Exception { 110 Invokable<?, Prepender> delegate = Prepender.constructor(String.class, int.class); 111 try { 112 delegate.returning(SubPrepender.class); 113 fail(); 114 } catch (IllegalArgumentException expected) {} 115 } 116 testStaticMethod_returnType()117 public void testStaticMethod_returnType() throws Exception { 118 Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class); 119 assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); 120 } 121 testStaticMethod_exceptionTypes()122 public void testStaticMethod_exceptionTypes() throws Exception { 123 Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class); 124 assertEquals(ImmutableList.of(), delegate.getExceptionTypes()); 125 } 126 testStaticMethod_typeParameters()127 public void testStaticMethod_typeParameters() throws Exception { 128 Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class); 129 TypeVariable<?>[] variables = delegate.getTypeParameters(); 130 assertEquals(1, variables.length); 131 assertEquals("T", variables[0].getName()); 132 } 133 testStaticMethod_parameters()134 public void testStaticMethod_parameters() throws Exception { 135 Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class); 136 ImmutableList<Parameter> parameters = delegate.getParameters(); 137 assertEquals(2, parameters.size()); 138 assertEquals(String.class, parameters.get(0).getType().getType()); 139 assertTrue(parameters.get(0).isAnnotationPresent(NotBlank.class)); 140 assertEquals(new TypeToken<Iterable<String>>() {}, parameters.get(1).getType()); 141 assertFalse(parameters.get(1).isAnnotationPresent(NotBlank.class)); 142 new EqualsTester() 143 .addEqualityGroup(parameters.get(0)) 144 .addEqualityGroup(parameters.get(1)) 145 .testEquals(); 146 } 147 testStaticMethod_call()148 public void testStaticMethod_call() throws Exception { 149 Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class); 150 @SuppressWarnings("unchecked") // prepend() returns Iterable<String> 151 Iterable<String> result = (Iterable<String>) 152 delegate.invoke(null, "a", ImmutableList.of("b", "c")); 153 assertEquals(ImmutableList.of("a", "b", "c"), ImmutableList.copyOf(result)); 154 } 155 testStaticMethod_returning()156 public void testStaticMethod_returning() throws Exception { 157 Invokable<?, Iterable<String>> delegate = Prepender.method( 158 "prepend", String.class, Iterable.class) 159 .returning(new TypeToken<Iterable<String>>() {}); 160 assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); 161 Iterable<String> result = delegate.invoke(null, "a", ImmutableList.of("b", "c")); 162 assertEquals(ImmutableList.of("a", "b", "c"), ImmutableList.copyOf(result)); 163 } 164 testStaticMethod_returningRawType()165 public void testStaticMethod_returningRawType() throws Exception { 166 @SuppressWarnings("rawtypes") // the purpose is to test raw type 167 Invokable<?, Iterable> delegate = Prepender.method( 168 "prepend", String.class, Iterable.class) 169 .returning(Iterable.class); 170 assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); 171 @SuppressWarnings("unchecked") // prepend() returns Iterable<String> 172 Iterable<String> result = delegate.invoke(null, "a", ImmutableList.of("b", "c")); 173 assertEquals(ImmutableList.of("a", "b", "c"), ImmutableList.copyOf(result)); 174 } 175 testStaticMethod_invalidReturning()176 public void testStaticMethod_invalidReturning() throws Exception { 177 Invokable<?, Object> delegate = Prepender.method("prepend", String.class, Iterable.class); 178 try { 179 delegate.returning(new TypeToken<Iterable<Integer>>() {}); 180 fail(); 181 } catch (IllegalArgumentException expected) {} 182 } 183 testInstanceMethod_returnType()184 public void testInstanceMethod_returnType() throws Exception { 185 Invokable<?, ?> delegate = Prepender.method("prepend", Iterable.class); 186 assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); 187 } 188 testInstanceMethod_exceptionTypes()189 public void testInstanceMethod_exceptionTypes() throws Exception { 190 Invokable<?, ?> delegate = Prepender.method("prepend", Iterable.class); 191 assertEquals( 192 ImmutableList.of( 193 TypeToken.of(IllegalArgumentException.class), 194 TypeToken.of(NullPointerException.class)), 195 delegate.getExceptionTypes()); 196 } 197 testInstanceMethod_typeParameters()198 public void testInstanceMethod_typeParameters() throws Exception { 199 Invokable<?, ?> delegate = Prepender.method("prepend", Iterable.class); 200 assertEquals(0, delegate.getTypeParameters().length); 201 } 202 testInstanceMethod_parameters()203 public void testInstanceMethod_parameters() throws Exception { 204 Invokable<?, ?> delegate = Prepender.method("prepend", Iterable.class); 205 ImmutableList<Parameter> parameters = delegate.getParameters(); 206 assertEquals(1, parameters.size()); 207 assertEquals(new TypeToken<Iterable<String>>() {}, parameters.get(0).getType()); 208 assertEquals(0, parameters.get(0).getAnnotations().length); 209 new EqualsTester() 210 .addEqualityGroup(parameters.get(0)) 211 .testEquals(); 212 } 213 testInstanceMethod_call()214 public void testInstanceMethod_call() throws Exception { 215 Invokable<Prepender, ?> delegate = Prepender.method("prepend", Iterable.class); 216 @SuppressWarnings("unchecked") // prepend() returns Iterable<String> 217 Iterable<String> result = (Iterable<String>) 218 delegate.invoke(new Prepender("a", 2), ImmutableList.of("b", "c")); 219 assertEquals(ImmutableList.of("a", "a", "b", "c"), ImmutableList.copyOf(result)); 220 } 221 testInstanceMethod_returning()222 public void testInstanceMethod_returning() throws Exception { 223 Invokable<Prepender, Iterable<String>> delegate = Prepender.method( 224 "prepend", Iterable.class) 225 .returning(new TypeToken<Iterable<String>>() {}); 226 assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); 227 Iterable<String> result = delegate.invoke(new Prepender("a", 2), ImmutableList.of("b", "c")); 228 assertEquals(ImmutableList.of("a", "a", "b", "c"), ImmutableList.copyOf(result)); 229 } 230 testInstanceMethod_returningRawType()231 public void testInstanceMethod_returningRawType() throws Exception { 232 @SuppressWarnings("rawtypes") // the purpose is to test raw type 233 Invokable<Prepender, Iterable> delegate = Prepender.method("prepend", Iterable.class) 234 .returning(Iterable.class); 235 assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); 236 @SuppressWarnings("unchecked") // prepend() returns Iterable<String> 237 Iterable<String> result = delegate.invoke( 238 new Prepender("a", 2), ImmutableList.of("b", "c")); 239 assertEquals(ImmutableList.of("a", "a", "b", "c"), ImmutableList.copyOf(result)); 240 } 241 testInstanceMethod_invalidReturning()242 public void testInstanceMethod_invalidReturning() throws Exception { 243 Invokable<?, Object> delegate = Prepender.method("prepend", Iterable.class); 244 try { 245 delegate.returning(new TypeToken<Iterable<Integer>>() {}); 246 fail(); 247 } catch (IllegalArgumentException expected) {} 248 } 249 testPrivateInstanceMethod_isOverridable()250 public void testPrivateInstanceMethod_isOverridable() throws Exception { 251 Invokable<?, ?> delegate = Prepender.method("privateMethod"); 252 assertTrue(delegate.isPrivate()); 253 assertFalse(delegate.isOverridable()); 254 assertFalse(delegate.isVarArgs()); 255 } 256 testPrivateFinalInstanceMethod_isOverridable()257 public void testPrivateFinalInstanceMethod_isOverridable() throws Exception { 258 Invokable<?, ?> delegate = Prepender.method("privateFinalMethod"); 259 assertTrue(delegate.isPrivate()); 260 assertTrue(delegate.isFinal()); 261 assertFalse(delegate.isOverridable()); 262 assertFalse(delegate.isVarArgs()); 263 } 264 testStaticMethod_isOverridable()265 public void testStaticMethod_isOverridable() throws Exception { 266 Invokable<?, ?> delegate = Prepender.method("staticMethod"); 267 assertTrue(delegate.isStatic()); 268 assertFalse(delegate.isOverridable()); 269 assertFalse(delegate.isVarArgs()); 270 } 271 testStaticFinalMethod_isFinal()272 public void testStaticFinalMethod_isFinal() throws Exception { 273 Invokable<?, ?> delegate = Prepender.method("staticFinalMethod"); 274 assertTrue(delegate.isStatic()); 275 assertTrue(delegate.isFinal()); 276 assertFalse(delegate.isOverridable()); 277 assertFalse(delegate.isVarArgs()); 278 } 279 280 static class Foo {} 281 testConstructor_isOverridablel()282 public void testConstructor_isOverridablel() throws Exception { 283 Invokable<?, ?> delegate = Invokable.from(Foo.class.getDeclaredConstructor()); 284 assertFalse(delegate.isOverridable()); 285 assertFalse(delegate.isVarArgs()); 286 } 287 testMethod_isVarArgs()288 public void testMethod_isVarArgs() throws Exception { 289 Invokable<?, ?> delegate = Prepender.method("privateVarArgsMethod", String[].class); 290 assertTrue(delegate.isVarArgs()); 291 } 292 testConstructor_isVarArgs()293 public void testConstructor_isVarArgs() throws Exception { 294 Invokable<?, ?> delegate = Prepender.constructor(String[].class); 295 assertTrue(delegate.isVarArgs()); 296 } 297 testGetOwnerType_constructor()298 public void testGetOwnerType_constructor() throws Exception { 299 Invokable<String, String> invokable = Invokable.from(String.class.getConstructor()); 300 assertEquals(TypeToken.of(String.class), invokable.getOwnerType()); 301 } 302 testGetOwnerType_method()303 public void testGetOwnerType_method() throws Exception { 304 Invokable<?, ?> invokable = Invokable.from(String.class.getMethod("length")); 305 assertEquals(TypeToken.of(String.class), invokable.getOwnerType()); 306 } 307 308 private static final class FinalClass { 309 @SuppressWarnings("unused") // used by reflection notFinalMethod()310 void notFinalMethod() {} 311 } 312 testNonFinalMethodInFinalClass_isOverridable()313 public void testNonFinalMethodInFinalClass_isOverridable() throws Exception { 314 Invokable<?, ?> delegate = Invokable.from( 315 FinalClass.class.getDeclaredMethod("notFinalMethod")); 316 assertFalse(delegate.isOverridable()); 317 assertFalse(delegate.isVarArgs()); 318 } 319 320 private class InnerWithDefaultConstructor { 321 class NestedInner {} 322 } 323 testInnerClassDefaultConstructor()324 public void testInnerClassDefaultConstructor() { 325 Constructor<?> constructor = 326 InnerWithDefaultConstructor.class.getDeclaredConstructors() [0]; 327 assertEquals(0, Invokable.from(constructor).getParameters().size()); 328 } 329 testNestedInnerClassDefaultConstructor()330 public void testNestedInnerClassDefaultConstructor() { 331 Constructor<?> constructor = 332 InnerWithDefaultConstructor.NestedInner.class.getDeclaredConstructors() [0]; 333 assertEquals(0, Invokable.from(constructor).getParameters().size()); 334 } 335 336 private class InnerWithOneParameterConstructor { 337 @SuppressWarnings("unused") // called by reflection InnerWithOneParameterConstructor(String s)338 public InnerWithOneParameterConstructor(String s) {} 339 } 340 testInnerClassWithOneParameterConstructor()341 public void testInnerClassWithOneParameterConstructor() { 342 Constructor<?> constructor = 343 InnerWithOneParameterConstructor.class.getDeclaredConstructors()[0]; 344 Invokable<?, ?> invokable = Invokable.from(constructor); 345 assertEquals(1, invokable.getParameters().size()); 346 assertEquals(TypeToken.of(String.class), invokable.getParameters().get(0).getType()); 347 } 348 349 private class InnerWithAnnotatedConstructorParameter { 350 @SuppressWarnings("unused") // called by reflection InnerWithAnnotatedConstructorParameter(@ullable String s)351 InnerWithAnnotatedConstructorParameter(@Nullable String s) {} 352 } 353 testInnerClassWithAnnotatedConstructorParameter()354 public void testInnerClassWithAnnotatedConstructorParameter() { 355 Constructor<?> constructor = 356 InnerWithAnnotatedConstructorParameter.class.getDeclaredConstructors() [0]; 357 Invokable<?, ?> invokable = Invokable.from(constructor); 358 assertEquals(1, invokable.getParameters().size()); 359 assertEquals(TypeToken.of(String.class), invokable.getParameters().get(0).getType()); 360 } 361 362 private class InnerWithGenericConstructorParameter { 363 @SuppressWarnings("unused") // called by reflection InnerWithGenericConstructorParameter(Iterable<String> it, String s)364 InnerWithGenericConstructorParameter(Iterable<String> it, String s) {} 365 } 366 testInnerClassWithGenericConstructorParameter()367 public void testInnerClassWithGenericConstructorParameter() { 368 Constructor<?> constructor = 369 InnerWithGenericConstructorParameter.class.getDeclaredConstructors() [0]; 370 Invokable<?, ?> invokable = Invokable.from(constructor); 371 assertEquals(2, invokable.getParameters().size()); 372 assertEquals(new TypeToken<Iterable<String>>() {}, 373 invokable.getParameters().get(0).getType()); 374 assertEquals(TypeToken.of(String.class), 375 invokable.getParameters().get(1).getType()); 376 } 377 testAnonymousClassDefaultConstructor()378 public void testAnonymousClassDefaultConstructor() { 379 final int i = 1; 380 final String s = "hello world"; 381 Class<?> anonymous = new Runnable() { 382 @Override public void run() { 383 System.out.println(s + i); 384 } 385 }.getClass(); 386 Constructor<?> constructor = anonymous.getDeclaredConstructors() [0]; 387 assertEquals(0, Invokable.from(constructor).getParameters().size()); 388 } 389 testAnonymousClassWithTwoParametersConstructor()390 public void testAnonymousClassWithTwoParametersConstructor() { 391 abstract class Base { 392 @SuppressWarnings("unused") // called by reflection 393 Base(String s, int i) {} 394 } 395 Class<?> anonymous = new Base("test", 0) {}.getClass(); 396 Constructor<?> constructor = anonymous.getDeclaredConstructors() [0]; 397 assertEquals(2, Invokable.from(constructor).getParameters().size()); 398 } 399 testLocalClassDefaultConstructor()400 public void testLocalClassDefaultConstructor() { 401 final int i = 1; 402 final String s = "hello world"; 403 class LocalWithDefaultConstructor implements Runnable { 404 @Override public void run() { 405 System.out.println(s + i); 406 } 407 } 408 Constructor<?> constructor = LocalWithDefaultConstructor.class.getDeclaredConstructors() [0]; 409 assertEquals(0, Invokable.from(constructor).getParameters().size()); 410 } 411 testStaticAnonymousClassDefaultConstructor()412 public void testStaticAnonymousClassDefaultConstructor() throws Exception { 413 doTestStaticAnonymousClassDefaultConstructor(); 414 } 415 doTestStaticAnonymousClassDefaultConstructor()416 private static void doTestStaticAnonymousClassDefaultConstructor() { 417 final int i = 1; 418 final String s = "hello world"; 419 Class<?> anonymous = new Runnable() { 420 @Override public void run() { 421 System.out.println(s + i); 422 } 423 }.getClass(); 424 Constructor<?> constructor = anonymous.getDeclaredConstructors() [0]; 425 assertEquals(0, Invokable.from(constructor).getParameters().size()); 426 } 427 testAnonymousClassInConstructor()428 public void testAnonymousClassInConstructor() { 429 new AnonymousClassInConstructor(); 430 } 431 432 private static class AnonymousClassInConstructor { AnonymousClassInConstructor()433 AnonymousClassInConstructor() { 434 final int i = 1; 435 final String s = "hello world"; 436 Class<?> anonymous = new Runnable() { 437 @Override public void run() { 438 System.out.println(s + i); 439 } 440 }.getClass(); 441 Constructor<?> constructor = anonymous.getDeclaredConstructors() [0]; 442 assertEquals(0, Invokable.from(constructor).getParameters().size()); 443 } 444 } 445 testLocalClassInInstanceInitializer()446 public void testLocalClassInInstanceInitializer() { 447 new LocalClassInInstanceInitializer(); 448 } 449 450 private static class LocalClassInInstanceInitializer { 451 { 452 class Local {} 453 Constructor<?> constructor = Local.class.getDeclaredConstructors() [0]; 454 assertEquals(0, Invokable.from(constructor).getParameters().size()); 455 } 456 } 457 testLocalClassInStaticInitializer()458 public void testLocalClassInStaticInitializer() { 459 new LocalClassInStaticInitializer(); 460 } 461 462 private static class LocalClassInStaticInitializer { 463 static { 464 class Local {} 465 Constructor<?> constructor = Local.class.getDeclaredConstructors() [0]; 466 assertEquals(0, Invokable.from(constructor).getParameters().size()); 467 } 468 } 469 testLocalClassWithSeeminglyHiddenThisInStaticInitializer_BUG()470 public void testLocalClassWithSeeminglyHiddenThisInStaticInitializer_BUG() { 471 new LocalClassWithSeeminglyHiddenThisInStaticInitializer(); 472 } 473 474 /** 475 * This class demonstrates a bug in getParameters() when the local class is inside static 476 * initializer. 477 */ 478 private static class LocalClassWithSeeminglyHiddenThisInStaticInitializer { 479 static { 480 class Local { 481 @SuppressWarnings("unused") // through reflection Local(LocalClassWithSeeminglyHiddenThisInStaticInitializer outer)482 Local(LocalClassWithSeeminglyHiddenThisInStaticInitializer outer) {} 483 } 484 Constructor<?> constructor = Local.class.getDeclaredConstructors() [0]; 485 int miscalculated = 0; assertEquals(miscalculated, Invokable.from(constructor).getParameters().size())486 assertEquals(miscalculated, Invokable.from(constructor).getParameters().size()); 487 } 488 } 489 testLocalClassWithOneParameterConstructor()490 public void testLocalClassWithOneParameterConstructor() throws Exception { 491 final int i = 1; 492 final String s = "hello world"; 493 class LocalWithOneParameterConstructor { 494 @SuppressWarnings("unused") // called by reflection 495 public LocalWithOneParameterConstructor(String x) { 496 System.out.println(s + i); 497 } 498 } 499 Constructor<?> constructor = 500 LocalWithOneParameterConstructor.class.getDeclaredConstructors()[0]; 501 Invokable<?, ?> invokable = Invokable.from(constructor); 502 assertEquals(1, invokable.getParameters().size()); 503 assertEquals(TypeToken.of(String.class), invokable.getParameters().get(0).getType()); 504 } 505 testLocalClassWithAnnotatedConstructorParameter()506 public void testLocalClassWithAnnotatedConstructorParameter() throws Exception { 507 class LocalWithAnnotatedConstructorParameter { 508 @SuppressWarnings("unused") // called by reflection 509 LocalWithAnnotatedConstructorParameter(@Nullable String s) {} 510 } 511 Constructor<?> constructor = 512 LocalWithAnnotatedConstructorParameter.class.getDeclaredConstructors() [0]; 513 Invokable<?, ?> invokable = Invokable.from(constructor); 514 assertEquals(1, invokable.getParameters().size()); 515 assertEquals(TypeToken.of(String.class), invokable.getParameters().get(0).getType()); 516 } 517 testLocalClassWithGenericConstructorParameter()518 public void testLocalClassWithGenericConstructorParameter() throws Exception { 519 class LocalWithGenericConstructorParameter { 520 @SuppressWarnings("unused") // called by reflection 521 LocalWithGenericConstructorParameter(Iterable<String> it, String s) {} 522 } 523 Constructor<?> constructor = 524 LocalWithGenericConstructorParameter.class.getDeclaredConstructors() [0]; 525 Invokable<?, ?> invokable = Invokable.from(constructor); 526 assertEquals(2, invokable.getParameters().size()); 527 assertEquals(new TypeToken<Iterable<String>>() {}, 528 invokable.getParameters().get(0).getType()); 529 assertEquals(TypeToken.of(String.class), 530 invokable.getParameters().get(1).getType()); 531 } 532 testEquals()533 public void testEquals() throws Exception { 534 new EqualsTester() 535 .addEqualityGroup(Prepender.constructor(), Prepender.constructor()) 536 .addEqualityGroup(Prepender.constructor(String.class, int.class)) 537 .addEqualityGroup(Prepender.method("privateMethod"), Prepender.method("privateMethod")) 538 .addEqualityGroup(Prepender.method("privateFinalMethod")) 539 .testEquals(); 540 } 541 testNulls()542 public void testNulls() { 543 new NullPointerTester().testAllPublicStaticMethods(Invokable.class); 544 new NullPointerTester().testAllPublicInstanceMethods(Prepender.method("staticMethod")); 545 } 546 547 @Retention(RetentionPolicy.RUNTIME) 548 private @interface NotBlank {} 549 550 /** Class for testing constructor, static method and instance method. */ 551 @SuppressWarnings("unused") // most are called by reflection 552 private static class Prepender { 553 554 private final String prefix; 555 private final int times; 556 Prepender(@otBlank String prefix, int times)557 Prepender(@NotBlank String prefix, int times) throws NullPointerException { 558 this.prefix = prefix; 559 this.times = times; 560 } 561 Prepender(String... varargs)562 Prepender(String... varargs) { 563 this(null, 0); 564 } 565 566 // just for testing Prepender()567 private <A> Prepender() { 568 this(null, 0); 569 } 570 prepend(@otBlank String first, Iterable<String> tail)571 static <T> Iterable<String> prepend(@NotBlank String first, Iterable<String> tail) { 572 return Iterables.concat(ImmutableList.of(first), tail); 573 } 574 prepend(Iterable<String> tail)575 Iterable<String> prepend(Iterable<String> tail) 576 throws IllegalArgumentException, NullPointerException { 577 return Iterables.concat(Collections.nCopies(times, prefix), tail); 578 } 579 constructor(Class<?>.... parameterTypes)580 static Invokable<?, Prepender> constructor(Class<?>... parameterTypes) throws Exception { 581 Constructor<Prepender> constructor = Prepender.class.getDeclaredConstructor(parameterTypes); 582 return Invokable.from(constructor); 583 } 584 method(String name, Class<?>... parameterTypes)585 static Invokable<Prepender, Object> method(String name, Class<?>... parameterTypes) { 586 try { 587 Method method = Prepender.class.getDeclaredMethod(name, parameterTypes); 588 @SuppressWarnings("unchecked") // The method is from Prepender. 589 Invokable<Prepender, Object> invokable = (Invokable<Prepender, Object>) 590 Invokable.from(method); 591 return invokable; 592 } catch (NoSuchMethodException e) { 593 throw new IllegalArgumentException(e); 594 } 595 } 596 privateMethod()597 private void privateMethod() {} 598 privateFinalMethod()599 private final void privateFinalMethod() {} 600 staticMethod()601 static void staticMethod() {} 602 staticFinalMethod()603 static final void staticFinalMethod() {} 604 privateVarArgsMethod(String... varargs)605 private void privateVarArgsMethod(String... varargs) {} 606 } 607 608 private static class SubPrepender extends Prepender { 609 @SuppressWarnings("unused") // needed to satisfy compiler, never called SubPrepender()610 public SubPrepender() throws NullPointerException { 611 throw new AssertionError(); 612 } 613 } 614 } 615