/*
* Copyright 2009 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.gwt.inject.rebind.util;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.replay;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.inject.client.Ginjector;
import com.google.gwt.inject.client.MyBindingAnnotation;
import com.google.gwt.inject.client.MyOtherAnnotation;
import com.google.gwt.inject.rebind.binding.Dependency;
import com.google.gwt.inject.rebind.reflect.FieldLiteral;
import com.google.gwt.inject.rebind.reflect.MethodLiteral;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import junit.framework.TestCase;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* Unit tests for {@link JType} to {@link Key} translation.
*/
public class GuiceUtilTest extends TestCase {
public void testGetKey_unAnnotatedMethod() throws NoSuchMethodException {
Key<?> key = getMethodKey("unAnnotated");
assertEquals(TypeLiteral.get(String.class), key.getTypeLiteral());
assertNull(key.getAnnotation());
}
public void testGetKey_bindingAnnotatedMethod() throws NoSuchMethodException {
Key<?> key = getMethodKey("bindingAnnotated");
assertEquals(TypeLiteral.get(String.class), key.getTypeLiteral());
assertEquals(MyBindingAnnotation.class, key.getAnnotationType());
}
public void testGetKey_legallyDoublyAnnotatedMethod() throws NoSuchMethodException {
Key<?> key = getMethodKey("legallyDoublyAnnotated");
assertEquals(TypeLiteral.get(String.class), key.getTypeLiteral());
assertEquals(MyBindingAnnotation.class, key.getAnnotationType());
}
public void testGetKey_illegallyDoublyAnnotatedMethod() throws NoSuchMethodException {
try {
getMethodKey("illegallyDoublyAnnotated");
fail("Expected ProvisionException.");
} catch (ProvisionException e) {
// Expected.
}
}
public void testGetKey_memberInjectUnAnnotatedMethod() throws NoSuchMethodException {
Key<?> key = getMethodKey("memberInjectUnAnnotated", String.class);
assertEquals(TypeLiteral.get(String.class), key.getTypeLiteral());
assertNull(key.getAnnotationType());
}
public void testGetKey_memberInjectAnnotatedMethod() throws NoSuchMethodException {
Key<?> key = getMethodKey("memberInjectAnnotated", String.class);
assertEquals(TypeLiteral.get(String.class), key.getTypeLiteral());
assertEquals(MyBindingAnnotation.class, key.getAnnotationType());
}
private Key<?> getMethodKey(String name, Class... parameters) throws NoSuchMethodException {
return new GuiceUtil(createInjectableCollector()).getKey(
(MethodLiteral<?, Method>) getMethod(name, parameters));
}
private MethodLiteral<?, Method> getMethod(String name, Class... parameters)
throws NoSuchMethodException {
return MethodLiteral.get(TestData.class.getDeclaredMethod(name, parameters),
TypeLiteral.get(TestData.class));
}
private MethodLiteral<?, ?> getNonGinjectorMethod() throws NoSuchMethodException {
return MethodLiteral.get(GuiceUtilTest.class.getDeclaredMethod("nonGinjectorMethod"),
TypeLiteral.get(GuiceUtilTest.class));
}
public void testGetKey_unAnnotatedField() throws NoSuchFieldException {
Key<?> key = getFieldKey("unAnnotated");
assertEquals(TypeLiteral.get(String.class), key.getTypeLiteral());
assertNull(key.getAnnotation());
}
public void testGetKey_bindingAnnotatedField() throws NoSuchFieldException {
Key<?> key = getFieldKey("bindingAnnotated");
assertEquals(TypeLiteral.get(String.class), key.getTypeLiteral());
assertEquals(MyBindingAnnotation.class, key.getAnnotationType());
}
public void testGetKey_legallyDoublyAnnotatedField() throws NoSuchFieldException {
Key<?> key = getFieldKey("legallyDoublyAnnotated");
assertEquals(TypeLiteral.get(String.class), key.getTypeLiteral());
assertEquals(MyBindingAnnotation.class, key.getAnnotationType());
}
public void testGetKey_illegallyDoublyAnnotatedField() throws NoSuchFieldException {
try {
getFieldKey("illegallyDoublyAnnotated");
fail("Expected ProvisionException.");
} catch (ProvisionException e) {
// Expected.
}
}
private Key<?> getFieldKey(String name) throws NoSuchFieldException {
return new GuiceUtil(createInjectableCollector()).getKey((FieldLiteral<?>) getField(name));
}
private FieldLiteral<?> getField(String name) throws NoSuchFieldException {
return FieldLiteral.get(TestData.class.getDeclaredField(name), TypeLiteral.get(TestData.class));
}
public void testIsMemberInject() throws NoSuchMethodException {
GuiceUtil guiceUtil = new GuiceUtil(createInjectableCollector());
assertFalse(guiceUtil.isMemberInject(getMethod("unAnnotated")));
assertTrue(guiceUtil.isMemberInject(getMethod("memberInjectUnAnnotated", String.class)));
}
public void testIsOptional_method() throws NoSuchMethodException {
GuiceUtil guiceUtil = new GuiceUtil(createInjectableCollector());
assertFalse(guiceUtil.isOptional(getMethod("nonOptionalInject")));
assertTrue(guiceUtil.isOptional(getMethod("optionalInject")));
assertFalse(guiceUtil.isOptional(getMethod("javaxInject")));
}
public void testIsOptional_field() throws NoSuchFieldException {
GuiceUtil guiceUtil = new GuiceUtil(createInjectableCollector());
assertFalse(guiceUtil.isOptional(getField("nonOptionalInject")));
assertTrue(guiceUtil.isOptional(getField("optionalInject")));
assertFalse(guiceUtil.isOptional(getField("javaxInject")));
}
private Set<Key<?>> extractKeys(Collection<Dependency> requiredKeys, boolean optional) {
Set<Key<?>> keySet = new HashSet<Key<?>>();
for (Dependency key : requiredKeys) {
if (key.isOptional() == optional) {
keySet.add(key.getTarget());
}
}
return keySet;
}
public void testGetRequiredKeys_method() throws NoSuchMethodException {
GuiceUtil guiceUtil = new GuiceUtil(createInjectableCollector());
Collection<Dependency> keys = guiceUtil.getDependencies(
Dependency.GINJECTOR, getMethod("nonOptionalKeys", String.class, Foo.class));
Set<Key<?>> optionalKeys = extractKeys(keys, true);
Set<Key<?>> requiredKeys = extractKeys(keys, false);
assertTrue(optionalKeys.isEmpty());
assertEquals(2, requiredKeys.size());
assertTrue(requiredKeys.contains(Key.get(String.class)));
assertTrue(requiredKeys.contains(Key.get(Foo.class)));
}
public void testGetRequiredKeys_optionalMethod() throws NoSuchMethodException {
GuiceUtil guiceUtil = new GuiceUtil(createInjectableCollector());
Collection<Dependency> keys = guiceUtil.getDependencies(
Dependency.GINJECTOR, getMethod("optionalKeys", String.class, Foo.class));
Set<Key<?>> optionalKeys = extractKeys(keys, true);
Set<Key<?>> requiredKeys = extractKeys(keys, false);
assertTrue(requiredKeys.isEmpty());
assertEquals(2, optionalKeys.size());
assertTrue(optionalKeys.contains(Key.get(String.class)));
assertTrue(optionalKeys.contains(Key.get(Foo.class)));
}
public void testGetRequiredKeys_noKeyMethod() throws NoSuchMethodException {
GuiceUtil guiceUtil = new GuiceUtil(createInjectableCollector());
Collection<Dependency> keys =
guiceUtil.getDependencies(Dependency.GINJECTOR, getMethod("noKeys"));
assertTrue(keys.isEmpty());
}
public void testGetRequiredKeys_annotatedKeysMethod() throws NoSuchMethodException {
GuiceUtil guiceUtil = new GuiceUtil(createInjectableCollector());
Collection<Dependency> keys =
guiceUtil.getDependencies(Dependency.GINJECTOR, getMethod("annotatedKeys", Foo.class));
Set<Key<?>> optionalKeys = extractKeys(keys, true);
Set<Key<?>> requiredKeys = extractKeys(keys, false);
assertTrue(optionalKeys.isEmpty());
assertEquals(1, requiredKeys.size());
assertTrue(requiredKeys.contains(Key.get(Foo.class, MyBindingAnnotation.class)));
}
public void testGetRequiredKeys_type() throws NoSuchMethodException, NoSuchFieldException {
MemberCollector memberCollector = createMock(MemberCollector.class);
Set<MethodLiteral<?, Method>> methods = new HashSet<MethodLiteral<?, Method>>();
methods.add(getMethod("nonOptionalKeys", String.class, Foo.class));
methods.add(getMethod("annotatedKeys", Foo.class));
Set<FieldLiteral<?>> fields = new HashSet<FieldLiteral<?>>();
fields.add(getField("unAnnotatedKey"));
fields.add(getField("annotatedKey"));
fields.add(getField("optionalKey"));
expect(memberCollector.getFields(TypeLiteral.get(TestData.class))).andReturn(fields);
expect(memberCollector.getMethods(TypeLiteral.get(TestData.class))).andReturn(methods);
replay(memberCollector);
GuiceUtil guiceUtil = new GuiceUtil(memberCollector);
Collection<Dependency> keys = guiceUtil.getMemberInjectionDependencies(
Dependency.GINJECTOR, TypeLiteral.get(TestData.class));
Set<Key<?>> optionalKeys = extractKeys(keys, true);
Set<Key<?>> requiredKeys = extractKeys(keys, false);
assertEquals(1, optionalKeys.size());
assertEquals(5, requiredKeys.size());
assertTrue(optionalKeys.contains(Key.get(Bar.class)));
assertTrue(requiredKeys.contains(Key.get(Baz.class)));
assertTrue(requiredKeys.contains(Key.get(Baz.class, MyBindingAnnotation.class)));
assertTrue(requiredKeys.contains(Key.get(String.class)));
assertTrue(requiredKeys.contains(Key.get(Foo.class)));
assertTrue(requiredKeys.contains(Key.get(Foo.class, MyBindingAnnotation.class)));
}
// TODO(schmitt): same collector as in the guice module, centralize.
private MemberCollector createInjectableCollector() {
MemberCollector collector = new MemberCollector(TreeLogger.NULL);
collector.setMethodFilter(
new MemberCollector.MethodFilter() {
public boolean accept(MethodLiteral<?, Method> method) {
// TODO(schmitt): Do injectable methods require at least one parameter?
return method.isAnnotationPresent(Inject.class) && !method.isStatic();
}
});
collector.setFieldFilter(
new MemberCollector.FieldFilter() {
public boolean accept(FieldLiteral<?> field) {
return field.isAnnotationPresent(Inject.class) && !field.isStatic();
}
});
return collector;
}
public static class TestData implements Ginjector {
String unAnnotated;
@MyBindingAnnotation String bindingAnnotated;
@MyBindingAnnotation @MyOtherAnnotation String legallyDoublyAnnotated;
@MyBindingAnnotation @Named("") String illegallyDoublyAnnotated;
@Inject String nonOptionalInject;
@Inject(optional = true) String optionalInject;
@javax.inject.Inject String javaxInject;
@Inject Baz unAnnotatedKey;
@Inject @MyBindingAnnotation Baz annotatedKey;
@Inject(optional = true) Bar optionalKey;
String unAnnotated() { return null; }
@MyBindingAnnotation String bindingAnnotated() { return null; }
@MyBindingAnnotation @MyOtherAnnotation String legallyDoublyAnnotated() { return null; }
@MyBindingAnnotation @Named("") String illegallyDoublyAnnotated() { return null; }
void memberInjectUnAnnotated(String string) {}
@MyBindingAnnotation void memberInjectAnnotated(String string) {}
@Inject void nonOptionalInject() {}
@Inject(optional = true) void optionalInject() {}
@javax.inject.Inject void javaxInject() {}
@Inject void nonOptionalKeys(String string, Foo foo) {}
@Inject(optional = true) void optionalKeys(String string, Foo foo) {}
@Inject void noKeys() {}
@Inject void annotatedKeys(@MyBindingAnnotation Foo foo) {}
}
public static class Foo {}
public static class Bar {}
public static class Baz {}
}