/core/test/com/google/inject/spi/SpiBindingsTest.java
Java | 463 lines | 389 code | 50 blank | 24 comment | 7 complexity | f1b8ffb6d8312e7b5fa2a4aaf65540cf MD5 | raw file
- /**
- * Copyright (C) 2008 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.spi;
- import static com.google.inject.Asserts.assertContains;
- import static com.google.inject.Asserts.getDeclaringSourcePart;
- import static com.google.inject.Asserts.isIncludeStackTraceComplete;
- import com.google.common.collect.ImmutableSet;
- import com.google.common.collect.Lists;
- import com.google.inject.AbstractModule;
- import com.google.inject.Binding;
- import com.google.inject.Guice;
- import com.google.inject.Inject;
- import com.google.inject.Injector;
- import com.google.inject.Key;
- import com.google.inject.Module;
- import com.google.inject.Provider;
- import com.google.inject.Scope;
- import com.google.inject.Scopes;
- import com.google.inject.Singleton;
- import com.google.inject.Stage;
- import com.google.inject.name.Names;
- import junit.framework.AssertionFailedError;
- import junit.framework.TestCase;
- import java.lang.reflect.Constructor;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.Iterator;
- import java.util.List;
- import java.util.concurrent.atomic.AtomicBoolean;
- import java.util.logging.Logger;
- /**
- * @author jessewilson@google.com (Jesse Wilson)
- */
- public class SpiBindingsTest extends TestCase {
- public void testBindConstant() {
- checkInjector(
- new AbstractModule() {
- protected void configure() {
- bindConstant().annotatedWith(Names.named("one")).to(1);
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> binding) {
- assertTrue(binding instanceof InstanceBinding);
- assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
- return null;
- }
- }
- );
- }
- public void testToInstanceBinding() {
- checkInjector(
- new AbstractModule() {
- protected void configure() {
- bind(String.class).toInstance("A");
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> binding) {
- assertTrue(binding instanceof InstanceBinding);
- checkBindingSource(binding);
- assertEquals(Key.get(String.class), binding.getKey());
- binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
- @Override public Void visit(InstanceBinding<? extends T> binding) {
- assertEquals("A", binding.getInstance());
- return null;
- }
- });
- binding.acceptScopingVisitor(new FailingBindingScopingVisitor() {
- public Void visitEagerSingleton() {
- return null;
- }
- });
- return null;
- }
- }
- );
- }
- public void testToProviderBinding() {
- final Provider<String> stringProvider = new StringProvider();
- checkInjector(
- new AbstractModule() {
- protected void configure() {
- bind(String.class).toProvider(stringProvider);
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> binding) {
- assertTrue(binding instanceof ProviderInstanceBinding);
- checkBindingSource(binding);
- assertEquals(Key.get(String.class), binding.getKey());
- binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
- @Override public Void visit(
- ProviderInstanceBinding<? extends T> binding) {
- assertSame(stringProvider, binding.getUserSuppliedProvider());
- return null;
- }
- });
- return null;
- }
- }
- );
- }
- public void testToProviderKeyBinding() {
- checkInjector(
- new AbstractModule() {
- protected void configure() {
- bind(String.class).toProvider(StringProvider.class);
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> binding) {
- assertTrue(binding instanceof ProviderKeyBinding);
- checkBindingSource(binding);
- assertEquals(Key.get(String.class), binding.getKey());
- binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
- @Override public Void visit(ProviderKeyBinding<? extends T> binding) {
- assertEquals(Key.get(StringProvider.class), binding.getProviderKey());
- return null;
- }
- });
- return null;
- }
- }
- );
- }
- public void testToKeyBinding() {
- final Key<String> aKey = Key.get(String.class, Names.named("a"));
- final Key<String> bKey = Key.get(String.class, Names.named("b"));
- checkInjector(
- new AbstractModule() {
- protected void configure() {
- bind(aKey).to(bKey);
- bind(bKey).toInstance("B");
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> binding) {
- assertTrue(binding instanceof LinkedKeyBinding);
- checkBindingSource(binding);
- assertEquals(aKey, binding.getKey());
- binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
- @Override public Void visit(LinkedKeyBinding<? extends T> binding) {
- assertEquals(bKey, binding.getLinkedKey());
- return null;
- }
- });
- return null;
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> binding) {
- assertEquals(bKey, binding.getKey());
- return null;
- }
- }
- );
- }
- public void testToConstructorBinding() {
- checkInjector(
- new AbstractModule() {
- protected void configure() {
- bind(D.class);
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> binding) {
- assertTrue(binding instanceof ConstructorBinding);
- checkBindingSource(binding);
- assertEquals(Key.get(D.class), binding.getKey());
- binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
- @Override public Void visit(ConstructorBinding<? extends T> binding) {
- Constructor<?> expected = D.class.getDeclaredConstructors()[0];
- assertEquals(expected, binding.getConstructor().getMember());
- assertEquals(ImmutableSet.<InjectionPoint>of(), binding.getInjectableMembers());
- return null;
- }
- });
- return null;
- }
- }
- );
- }
- public void testConstantBinding() {
- checkInjector(
- new AbstractModule() {
- protected void configure() {
- bindConstant().annotatedWith(Names.named("one")).to(1);
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> binding) {
- assertTrue(binding instanceof InstanceBinding);
- checkBindingSource(binding);
- assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
- binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
- @Override public Void visit(InstanceBinding<? extends T> binding) {
- assertEquals(1, binding.getInstance());
- return null;
- }
- });
- return null;
- }
- }
- );
- }
- public void testConvertedConstantBinding() {
- Injector injector = Guice.createInjector(new AbstractModule() {
- protected void configure() {
- bindConstant().annotatedWith(Names.named("one")).to("1");
- }
- });
- Binding<Integer> binding = injector.getBinding(Key.get(Integer.class, Names.named("one")));
- assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
- checkBindingSource(binding);
- assertTrue(binding instanceof ConvertedConstantBinding);
- binding.acceptTargetVisitor(new FailingTargetVisitor<Integer>() {
- @Override public Void visit(
- ConvertedConstantBinding<? extends Integer> binding) {
- assertEquals((Integer) 1, binding.getValue());
- assertEquals(Key.get(String.class, Names.named("one")), binding.getSourceKey());
- return null;
- }
- });
- }
- public void testProviderBinding() {
- Injector injector = Guice.createInjector(new AbstractModule() {
- protected void configure() {
- bind(String.class).toInstance("A");
- }
- });
- Key<Provider<String>> providerOfStringKey = new Key<Provider<String>>() {};
- Binding<Provider<String>> binding = injector.getBinding(providerOfStringKey);
- assertEquals(providerOfStringKey, binding.getKey());
- checkBindingSource(binding);
- assertTrue(binding instanceof ProviderBinding);
- binding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
- @Override public Void visit(
- ProviderBinding<? extends Provider<String>> binding) {
- assertEquals(Key.get(String.class), binding.getProvidedKey());
- return null;
- }
- });
- }
- public void testScopes() {
- checkInjector(
- new AbstractModule() {
- protected void configure() {
- bind(String.class).annotatedWith(Names.named("a"))
- .toProvider(StringProvider.class).in(Singleton.class);
- bind(String.class).annotatedWith(Names.named("b"))
- .toProvider(StringProvider.class).in(Scopes.SINGLETON);
- bind(String.class).annotatedWith(Names.named("c"))
- .toProvider(StringProvider.class).asEagerSingleton();
- bind(String.class).annotatedWith(Names.named("d"))
- .toProvider(StringProvider.class);
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> command) {
- assertEquals(Key.get(String.class, Names.named("a")), command.getKey());
- command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
- @Override public Void visitScope(Scope scope) {
- // even though we bound with an annotation, the injector always uses instances
- assertSame(Scopes.SINGLETON, scope);
- return null;
- }
- });
- return null;
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> command) {
- assertEquals(Key.get(String.class, Names.named("b")), command.getKey());
- command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
- @Override public Void visitScope(Scope scope) {
- assertSame(Scopes.SINGLETON, scope);
- return null;
- }
- });
- return null;
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> command) {
- assertEquals(Key.get(String.class, Names.named("c")), command.getKey());
- command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
- @Override public Void visitEagerSingleton() {
- return null;
- }
- });
- return null;
- }
- },
- new FailingElementVisitor() {
- @Override public <T> Void visit(Binding<T> command) {
- assertEquals(Key.get(String.class, Names.named("d")), command.getKey());
- command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
- @Override public Void visitNoScoping() {
- return null;
- }
- });
- return null;
- }
- }
- );
- }
-
- public void testExtensionSpi() {
- final AtomicBoolean visiting = new AtomicBoolean(false);
-
- final Injector injector = Guice.createInjector(new AbstractModule() {
- protected void configure() {
- bind(String.class).toProvider(new ProviderWithExtensionVisitor<String>() {
- public <B, V> V acceptExtensionVisitor(BindingTargetVisitor<B, V> visitor,
- ProviderInstanceBinding<? extends B> binding) {
- assertSame(this, binding.getUserSuppliedProvider());
- // We can't always check for FailingSpiTargetVisitor,
- // because constructing the injector visits here, and we need
- // to process the binding as normal
- if(visiting.get()) {
- assertTrue("visitor: " + visitor, visitor instanceof FailingSpiTargetVisitor);
- return (V)"visited";
- } else {
- return visitor.visit(binding);
- }
- }
-
- public String get() {
- return "FooBar";
- }
- });
- }
- });
-
- visiting.set(true);
- // Check for Provider<String> binding -- that is still a ProviderBinding.
- Key<Provider<String>> providerOfStringKey = new Key<Provider<String>>() {};
- Binding<Provider<String>> providerBinding = injector.getBinding(providerOfStringKey);
- assertEquals(providerOfStringKey, providerBinding.getKey());
- checkBindingSource(providerBinding);
- assertTrue("binding: " + providerBinding, providerBinding instanceof ProviderBinding);
- providerBinding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
- @Override public Void visit(ProviderBinding<? extends Provider<String>> binding) {
- assertEquals(Key.get(String.class), binding.getProvidedKey());
- return null;
- }
- });
-
- // Check for String binding -- that one is ProviderInstanceBinding, and gets hooked
- Binding<String> binding = injector.getBinding(String.class);
- assertEquals(Key.get(String.class), binding.getKey());
- checkBindingSource(binding);
- assertTrue(binding instanceof ProviderInstanceBinding);
- assertEquals("visited", binding.acceptTargetVisitor(new FailingSpiTargetVisitor<String>()));
- }
- private static class FailingSpiTargetVisitor<T> extends DefaultBindingTargetVisitor<T, String> {
- @Override
- protected String visitOther(Binding<? extends T> binding) {
- throw new AssertionFailedError();
- }
- }
- public void checkBindingSource(Binding binding) {
- assertContains(binding.getSource().toString(), getDeclaringSourcePart(getClass()));
- ElementSource source = (ElementSource) binding.getSource();
- assertFalse(source.getModuleClassNames().isEmpty());
- if (isIncludeStackTraceComplete()) {
- assertTrue(source.getStackTrace().length > 0);
- } else {
- assertEquals(0, source.getStackTrace().length);
- }
- }
-
- public void checkInjector(Module module, ElementVisitor<?>... visitors) {
- Injector injector = Guice.createInjector(module);
- List<Binding<?>> bindings = Lists.newArrayList(injector.getBindings().values());
- for (Iterator<Binding<?>> i = bindings.iterator(); i.hasNext(); ) {
- if (BUILT_IN_BINDINGS.contains(i.next().getKey())) {
- i.remove();
- }
- }
- Collections.sort(bindings, orderByKey);
- assertEquals(bindings.size(), visitors.length);
- for (int i = 0; i < visitors.length; i++) {
- ElementVisitor<?> visitor = visitors[i];
- Binding<?> binding = bindings.get(i);
- binding.acceptVisitor(visitor);
- }
- }
- private final ImmutableSet<Key<?>> BUILT_IN_BINDINGS = ImmutableSet.of(
- Key.get(Injector.class), Key.get(Stage.class), Key.get(Logger.class));
- private final Comparator<Binding<?>> orderByKey = new Comparator<Binding<?>>() {
- public int compare(Binding<?> a, Binding<?> b) {
- return a.getKey().toString().compareTo(b.getKey().toString());
- }
- };
- private static class StringProvider implements Provider<String> {
- public String get() {
- return "A";
- }
- }
- private static class C { }
- private static class D extends C {
- @Inject public D(Injector unused) { }
- }
- }