Add a Maven module for JDK8-specific tests to open-source Guice.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=78097782
diff --git a/jdk8-tests/pom.xml b/jdk8-tests/pom.xml
new file mode 100644
index 0000000..a5877fe
--- /dev/null
+++ b/jdk8-tests/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Copyright (c) 2014 Google, Inc. All rights reserved.
+
+This program is licensed to you under the Apache License Version 2.0,
+and you may not use this file except in compliance with the Apache License Version 2.0.
+You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the Apache License Version 2.0 is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>guice-parent</artifactId>
+ <groupId>com.google.inject</groupId>
+ <version>4.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>jdk8-tests</artifactId>
+
+ <name>Google Guice - JDK8 Tests</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ <version>${parent.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava-testlib</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>8</source>
+ <target>8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/jdk8-tests/test/com/google/inject/jdk8/DefaultMethodInterceptionTest.java b/jdk8-tests/test/com/google/inject/jdk8/DefaultMethodInterceptionTest.java
new file mode 100644
index 0000000..29e0681
--- /dev/null
+++ b/jdk8-tests/test/com/google/inject/jdk8/DefaultMethodInterceptionTest.java
@@ -0,0 +1,223 @@
+/**
+ * Copyright (C) 2014 Google Inc.
+ *
+ * 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.inject.jdk8;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.matcher.Matchers;
+
+import junit.framework.TestCase;
+
+import org.aopalliance.intercept.MethodInterceptor;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests for interception of default methods.
+ *
+ * @author cgdecker@google.com (Colin Decker)
+ */
+public class DefaultMethodInterceptionTest extends TestCase {
+
+ private static final AtomicInteger callCount = new AtomicInteger(0);
+ private static final AtomicInteger interceptedCallCount = new AtomicInteger(0);
+
+ // the interceptor's a lambda too
+ private final MethodInterceptor interceptor = invocation -> {
+ interceptedCallCount.incrementAndGet();
+ return invocation.proceed();
+ };
+
+ @Override
+ protected void setUp() throws Exception {
+ callCount.set(0);
+ interceptedCallCount.set(0);
+ }
+
+ @Retention(RUNTIME)
+ @Target({METHOD, TYPE})
+ public @interface InterceptMe {}
+
+ /** Interface with a default method annotated to be intercepted. */
+ public interface Foo {
+ @InterceptMe
+ default String defaultMethod() {
+ callCount.incrementAndGet();
+ return "Foo";
+ }
+ }
+
+ /** Foo implementation that does not override the default method. */
+ public static class NonOverridingFoo implements Foo {
+ public String methodCallingDefault() {
+ return "NonOverriding-" + defaultMethod();
+ }
+ }
+
+ public void testInterceptedDefaultMethod() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
+ interceptor);
+ bind(Foo.class).to(NonOverridingFoo.class);
+ }
+ });
+
+ Foo foo = injector.getInstance(Foo.class);
+ assertEquals("Foo", foo.defaultMethod());
+ assertEquals(1, callCount.get());
+ assertEquals(1, interceptedCallCount.get());
+ }
+
+ public void testInterceptedDefaultMethod_calledByAnotherMethod() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
+ interceptor);
+ }
+ });
+
+ NonOverridingFoo foo = injector.getInstance(NonOverridingFoo.class);
+ assertEquals("NonOverriding-Foo", foo.methodCallingDefault());
+ assertEquals(1, callCount.get());
+ assertEquals(1, interceptedCallCount.get());
+ }
+
+ /** A base class defining a method with the same signature as Foo's default method. */
+ public static class BaseClass {
+ // the definition of this method on the class will win over the default method
+ public String defaultMethod() {
+ callCount.incrementAndGet();
+ return "BaseClass";
+ }
+ }
+
+ /** Foo implementation that should use superclass method rather than default method. */
+ public static class InheritingFoo extends BaseClass implements Foo {
+ }
+
+ public void testInterceptedDefaultMethod_whenParentClassDefinesNonInterceptedMethod() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
+ interceptor);
+ bind(Foo.class).to(InheritingFoo.class);
+ }
+ });
+
+ // the concrete implementation that wins is not annotated
+ Foo foo = injector.getInstance(Foo.class);
+ assertEquals("BaseClass", foo.defaultMethod());
+ assertEquals(1, callCount.get());
+ assertEquals(0, interceptedCallCount.get());
+ }
+
+ /**
+ * A base class defining an intercepted method with the same signature as Foo's default method.
+ */
+ public static class BaseClass2 {
+ // the definition of this method on the class will win over the default method
+ @InterceptMe
+ public String defaultMethod() {
+ callCount.incrementAndGet();
+ return "BaseClass2";
+ }
+ }
+
+ /**
+ * Foo implementation that should use intercepted superclass method rather than default method.
+ */
+ public static class InheritingFoo2 extends BaseClass2 implements Foo {
+ }
+
+ public void testInterceptedDefaultMethod_whenParentClassDefinesInterceptedMethod() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bindInterceptor(Matchers.any(), Matchers.annotatedWith(InterceptMe.class),
+ interceptor);
+ bind(Foo.class).to(InheritingFoo2.class);
+ }
+ });
+
+ // the concrete implementation that wins is not annotated
+ Foo foo = injector.getInstance(Foo.class);
+ assertEquals("BaseClass2", foo.defaultMethod());
+ assertEquals(1, callCount.get());
+ assertEquals(1, interceptedCallCount.get());
+ }
+
+ public interface Baz {
+ default String doSomething() {
+ return "Baz";
+ }
+
+ String doSomethingElse();
+ }
+
+ public static class BazImpl implements Baz {
+
+ @Override
+ public String doSomethingElse() {
+ return "BazImpl";
+ }
+ }
+
+ public void testInterception_ofAllMethodsOnType() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bindInterceptor(Matchers.subclassesOf(Baz.class), Matchers.any(), interceptor);
+ bind(Baz.class).to(BazImpl.class);
+ }
+ });
+
+ Baz baz = injector.getInstance(Baz.class);
+
+ assertEquals("Baz", baz.doSomething());
+ assertEquals("BazImpl", baz.doSomethingElse());
+
+ assertEquals(2, interceptedCallCount.get());
+ }
+
+ public void testInterception_ofAllMethodsOnType_interceptsInheritedDefaultMethod() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bindInterceptor(Matchers.subclassesOf(BazImpl.class), Matchers.any(), interceptor);
+ bind(Baz.class).to(BazImpl.class);
+ }
+ });
+
+ Baz baz = injector.getInstance(Baz.class);
+
+ assertEquals("Baz", baz.doSomething());
+ assertEquals("BazImpl", baz.doSomethingElse());
+
+ assertEquals(2, interceptedCallCount.get());
+ }
+}
diff --git a/jdk8-tests/test/com/google/inject/jdk8/Java8LanguageFeatureBindingTest.java b/jdk8-tests/test/com/google/inject/jdk8/Java8LanguageFeatureBindingTest.java
new file mode 100644
index 0000000..9c57cd3
--- /dev/null
+++ b/jdk8-tests/test/com/google/inject/jdk8/Java8LanguageFeatureBindingTest.java
@@ -0,0 +1,165 @@
+/**
+ * Copyright (C) 2014 Google Inc.
+ *
+ * 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.inject.jdk8;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.ProvisionException;
+import com.google.inject.TypeLiteral;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
+
+/**
+ * Test bindings to lambdas, method references, etc.
+ *
+ * @author cgdecker@google.com (Colin Decker)
+ */
+public class Java8LanguageFeatureBindingTest extends TestCase {
+
+ // Some of these tests are kind of weird.
+ // See https://github.com/google/guice/issues/757 for more on why they exist.
+
+ public void testBinding_lambdaToInterface() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(new TypeLiteral<Predicate<Object>>() {}).toInstance(o -> o != null);
+ }
+ });
+
+ Predicate<Object> predicate = injector.getInstance(new Key<Predicate<Object>>() {});
+ assertTrue(predicate.test(new Object()));
+ assertFalse(predicate.test(null));
+ }
+
+ public void testProviderMethod_returningLambda() throws Exception {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {}
+
+ @Provides
+ public Callable<String> provideCallable() {
+ return () -> "foo";
+ }
+ });
+
+ Callable<String> callable = injector.getInstance(new Key<Callable<String>>() {});
+ assertEquals("foo", callable.call());
+ }
+
+ public void testProviderMethod_containingLambda_throwingException() throws Exception {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {}
+
+ @Provides
+ public Callable<String> provideCallable() {
+ if (Boolean.parseBoolean("false")) { // avoid dead code warnings
+ return () -> "foo";
+ } else {
+ throw new RuntimeException("foo");
+ }
+ }
+ });
+
+ try {
+ injector.getInstance(new Key<Callable<String>>() {});
+ } catch (ProvisionException expected) {
+ assertTrue(expected.getCause() instanceof RuntimeException);
+ assertEquals("foo", expected.getCause().getMessage());
+ }
+ }
+
+ public void testProvider_usingJdk8Features() {
+ try {
+ Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).toProvider(StringProvider.class);
+ }
+ });
+
+ fail();
+ } catch (CreationException expected) {
+ }
+
+ UUID uuid = UUID.randomUUID();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(UUID.class).toInstance(uuid);
+ bind(String.class).toProvider(StringProvider.class);
+ }
+ });
+
+ assertEquals(uuid.toString(), injector.getInstance(String.class));
+ }
+
+ private static final class StringProvider implements Provider<String> {
+ private final UUID uuid;
+
+ @Inject
+ StringProvider(UUID uuid) {
+ this.uuid = uuid;
+ }
+
+ @Override
+ public String get() {
+ return Collections.singleton(uuid).stream()
+ .map(UUID::toString)
+ .findFirst().get();
+ }
+ }
+
+ public void testBinding_toProvider_lambda() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ AtomicInteger i = new AtomicInteger();
+ bind(String.class).toProvider(() -> "Hello" + i.incrementAndGet());
+ }
+ });
+
+ assertEquals("Hello1", injector.getInstance(String.class));
+ assertEquals("Hello2", injector.getInstance(String.class));
+ }
+
+ public void testBinding_toProvider_methodReference() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(String.class).toProvider(Java8LanguageFeatureBindingTest.this::provideString);
+ }
+ });
+
+ Provider<String> provider = injector.getProvider(String.class);
+ assertEquals("Hello", provider.get());
+ }
+
+ private String provideString() {
+ return "Hello";
+ }
+}
diff --git a/pom.xml b/pom.xml
index cc93bc7..7ded5d8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,7 @@
<modules>
<module>core</module>
<module>extensions</module>
+ <!-- jdk8-tests module activated only when running under JDK8, below -->
</modules>
<prerequisites>
@@ -431,12 +432,17 @@
<profiles>
<profile>
- <id>doclint-java8-disable</id>
+ <id>java8</id>
<activation>
<jdk>[1.8,)</jdk>
</activation>
+ <modules>
+ <!-- Activate jdk8-tests module only under JDK 8 -->
+ <module>jdk8-tests</module>
+ </modules>
<build>
<plugins>
+ <!-- Disable doclint under JDK 8 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>