Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test case for additional failure cases. #1

Draft
wants to merge 5 commits into
base: issue-1133-prototype-cglib-replacement
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 236 additions & 0 deletions core/test/com/google/inject/CglibRemovalTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
package com.google.inject;

import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

import com.google.common.testing.NullPointerTester;
import com.google.common.util.concurrent.ExecutionError;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.matcher.Matchers;
import com.google.inject.testing.NullpointerObject;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.function.Function;
import junit.framework.TestCase;
import org.junit.Test;

public class CglibRemovalTest extends TestCase {
interface Interface {
int method();
}

static class Impl implements Interface {
private final String str;

@Inject
Impl(String str) {
this.str = str;
}

@Override
public int method() {
return str.hashCode();
}
}

private static final String STRING = "foobar";

static class TestModule extends AbstractModule {
@Override
protected void configure() {
bind(String.class).toInstance(STRING);
bind(Interface.class).to(Impl.class);
}
}

static class InterceptorModule extends AbstractModule {
@Override
protected void configure() {
// Test passes if no interceptor is bound.
bindInterceptor(Matchers.any(), Matchers.returns(Matchers.subclassesOf(int.class)),
invocation -> invocation.proceed());
}
}

@Test
public void testUseInjectedClass() throws Throwable {
Interface instance = Guice.createInjector(new TestModule(), new InterceptorModule()).getInstance(Interface.class);
Class<? extends Interface> klass = instance.getClass();
MethodHandles.Lookup lookup = MethodHandles.lookup();
CallSite callsite = LambdaMetafactory.metafactory(
lookup,
"apply",
MethodType.methodType(Function.class),
MethodType.methodType(Object.class, Object.class),
lookup.findVirtual(klass, "method", MethodType.methodType(int.class)),
MethodType.methodType(int.class, klass)
);
Object res = ((Function)callsite.getTarget().invokeExact()).apply(instance);
assertEquals(STRING.hashCode(), res);
}

@Test
public void testMockitoSpy() throws Exception {
Interface instance = spy(Guice.createInjector(
new TestModule(),
new InterceptorModule()
).getInstance(Interface.class));

instance.method();
verify(instance).method();
}

@Test
public void testMethodMatcherError() throws Exception {
Module interceptorModule = new AbstractModule() {
@Override
protected void configure() {
bindInterceptor(Matchers.subclassesOf(Interface.class), new AbstractMatcher<Method>() {
@Override
public boolean matches(Method method) {
if (method.getReturnType().isPrimitive()) {
throw new IllegalArgumentException("can't intercept method " + method.getName());
}
return true;
}
},
invocation -> invocation.proceed());
}
};
try {
Guice.createInjector(new TestModule(), interceptorModule);
fail("should fail");
} catch (UncheckedExecutionException e) {
assertTrue(e.getCause() instanceof IllegalArgumentException);
}
}

private static class PrivateConstructor {
int method() {
return 1;
}
}

@Test
public void testPrivateConstructor() {
Injector injector = Guice.createInjector(new InterceptorModule());
try {
injector.getInstance(PrivateConstructor.class);
fail("should fail");
} catch (ConfigurationException e) {
assertTrue(e.getCause() instanceof IllegalArgumentException);
}
}

static class ConstructorThrowsException {
@Inject static ConstructorThrowsException instance;

@Inject
ConstructorThrowsException() throws Exception {
throw new ExecutionError("failed", new IllegalAccessError("failed"));
}
}

@Test
public void testStaticInjection() {
try {
Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
requestStaticInjection(ConstructorThrowsException.class);
}
});
fail("expected to fail");
} catch (CreationException e) {
// expected
}
}


static class Foo {
@Inject
Foo() {
throw new AssertionError("fail!");
}
}

@Test
public void testAssertionErrorInConstructor() {
Injector injector = Guice.createInjector();
try {
injector.getInstance(Foo.class);
fail("expected to throw exception");
} catch (RuntimeException e) {
// expected.
}
}

@Test
public void testEnhancedMethodVisibility() {
NullpointerObject object = Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bindInterceptor(Matchers.any(), Matchers.annotatedWith(NullpointerObject.Intercept.class),
invocation -> invocation.proceed());
}
}
).getInstance(NullpointerObject.class);
new NullPointerTester().testAllPublicInstanceMethods(object);
}

@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface Measure {}

static abstract class Base<T> {
protected final T t;

protected Base(T t) {
this.t = t;
}

protected T getT() {return t;}
}

static abstract class Subclass<F> extends Base<String> {
protected Subclass(String t) {
super(t);
}

protected abstract void otherMethod(F f);

@Override
protected final String getT() {return t;}
}

@Measure
static class SubSubClass extends Subclass<String> {
@Inject
SubSubClass() {
super("");
}

@Override
protected final void otherMethod(String s) {}
}

@Test
public void testOverrideFinalMethod() {
Class<?> c = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindInterceptor(Matchers.annotatedWith(Measure.class), Matchers.any(), invocation -> invocation.proceed());
}
}).getInstance(SubSubClass.class)
.getClass();
assertNotNull(c.getCanonicalName());
}
}
5 changes: 5 additions & 0 deletions core/test/com/google/inject/testing/Action.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.google.inject.testing;

public interface Action {

}
38 changes: 38 additions & 0 deletions core/test/com/google/inject/testing/NullpointerObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.google.inject.testing;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Inject;

public class NullpointerObject implements Action {
@Retention(RetentionPolicy.RUNTIME)
public @interface Intercept {}

static class TestObject {

private final int i;

TestObject(int i) {
this.i = i;
}
}

@Inject
NullpointerObject() {
}

@Intercept
void method(TestObject object) throws Exception {
method(10, object);
}

@Intercept
void otherMethod(TestObject o) throws IOException {
throw new IOException("o");
}

private void method(int i, TestObject object) {
System.out.println(object.i - i);
}
}
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ See the Apache License Version 2.0 for the specific language governing permissio
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down