PageRenderTime 24ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/core/test/com/google/inject/spi/SpiBindingsTest.java

https://gitlab.com/metamorphiccode/guice
Java | 463 lines | 389 code | 50 blank | 24 comment | 7 complexity | f1b8ffb6d8312e7b5fa2a4aaf65540cf MD5 | raw file
  1. /**
  2. * Copyright (C) 2008 Google Inc.
  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. package com.google.inject.spi;
  17. import static com.google.inject.Asserts.assertContains;
  18. import static com.google.inject.Asserts.getDeclaringSourcePart;
  19. import static com.google.inject.Asserts.isIncludeStackTraceComplete;
  20. import com.google.common.collect.ImmutableSet;
  21. import com.google.common.collect.Lists;
  22. import com.google.inject.AbstractModule;
  23. import com.google.inject.Binding;
  24. import com.google.inject.Guice;
  25. import com.google.inject.Inject;
  26. import com.google.inject.Injector;
  27. import com.google.inject.Key;
  28. import com.google.inject.Module;
  29. import com.google.inject.Provider;
  30. import com.google.inject.Scope;
  31. import com.google.inject.Scopes;
  32. import com.google.inject.Singleton;
  33. import com.google.inject.Stage;
  34. import com.google.inject.name.Names;
  35. import junit.framework.AssertionFailedError;
  36. import junit.framework.TestCase;
  37. import java.lang.reflect.Constructor;
  38. import java.util.Collections;
  39. import java.util.Comparator;
  40. import java.util.Iterator;
  41. import java.util.List;
  42. import java.util.concurrent.atomic.AtomicBoolean;
  43. import java.util.logging.Logger;
  44. /**
  45. * @author jessewilson@google.com (Jesse Wilson)
  46. */
  47. public class SpiBindingsTest extends TestCase {
  48. public void testBindConstant() {
  49. checkInjector(
  50. new AbstractModule() {
  51. protected void configure() {
  52. bindConstant().annotatedWith(Names.named("one")).to(1);
  53. }
  54. },
  55. new FailingElementVisitor() {
  56. @Override public <T> Void visit(Binding<T> binding) {
  57. assertTrue(binding instanceof InstanceBinding);
  58. assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
  59. return null;
  60. }
  61. }
  62. );
  63. }
  64. public void testToInstanceBinding() {
  65. checkInjector(
  66. new AbstractModule() {
  67. protected void configure() {
  68. bind(String.class).toInstance("A");
  69. }
  70. },
  71. new FailingElementVisitor() {
  72. @Override public <T> Void visit(Binding<T> binding) {
  73. assertTrue(binding instanceof InstanceBinding);
  74. checkBindingSource(binding);
  75. assertEquals(Key.get(String.class), binding.getKey());
  76. binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
  77. @Override public Void visit(InstanceBinding<? extends T> binding) {
  78. assertEquals("A", binding.getInstance());
  79. return null;
  80. }
  81. });
  82. binding.acceptScopingVisitor(new FailingBindingScopingVisitor() {
  83. public Void visitEagerSingleton() {
  84. return null;
  85. }
  86. });
  87. return null;
  88. }
  89. }
  90. );
  91. }
  92. public void testToProviderBinding() {
  93. final Provider<String> stringProvider = new StringProvider();
  94. checkInjector(
  95. new AbstractModule() {
  96. protected void configure() {
  97. bind(String.class).toProvider(stringProvider);
  98. }
  99. },
  100. new FailingElementVisitor() {
  101. @Override public <T> Void visit(Binding<T> binding) {
  102. assertTrue(binding instanceof ProviderInstanceBinding);
  103. checkBindingSource(binding);
  104. assertEquals(Key.get(String.class), binding.getKey());
  105. binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
  106. @Override public Void visit(
  107. ProviderInstanceBinding<? extends T> binding) {
  108. assertSame(stringProvider, binding.getUserSuppliedProvider());
  109. return null;
  110. }
  111. });
  112. return null;
  113. }
  114. }
  115. );
  116. }
  117. public void testToProviderKeyBinding() {
  118. checkInjector(
  119. new AbstractModule() {
  120. protected void configure() {
  121. bind(String.class).toProvider(StringProvider.class);
  122. }
  123. },
  124. new FailingElementVisitor() {
  125. @Override public <T> Void visit(Binding<T> binding) {
  126. assertTrue(binding instanceof ProviderKeyBinding);
  127. checkBindingSource(binding);
  128. assertEquals(Key.get(String.class), binding.getKey());
  129. binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
  130. @Override public Void visit(ProviderKeyBinding<? extends T> binding) {
  131. assertEquals(Key.get(StringProvider.class), binding.getProviderKey());
  132. return null;
  133. }
  134. });
  135. return null;
  136. }
  137. }
  138. );
  139. }
  140. public void testToKeyBinding() {
  141. final Key<String> aKey = Key.get(String.class, Names.named("a"));
  142. final Key<String> bKey = Key.get(String.class, Names.named("b"));
  143. checkInjector(
  144. new AbstractModule() {
  145. protected void configure() {
  146. bind(aKey).to(bKey);
  147. bind(bKey).toInstance("B");
  148. }
  149. },
  150. new FailingElementVisitor() {
  151. @Override public <T> Void visit(Binding<T> binding) {
  152. assertTrue(binding instanceof LinkedKeyBinding);
  153. checkBindingSource(binding);
  154. assertEquals(aKey, binding.getKey());
  155. binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
  156. @Override public Void visit(LinkedKeyBinding<? extends T> binding) {
  157. assertEquals(bKey, binding.getLinkedKey());
  158. return null;
  159. }
  160. });
  161. return null;
  162. }
  163. },
  164. new FailingElementVisitor() {
  165. @Override public <T> Void visit(Binding<T> binding) {
  166. assertEquals(bKey, binding.getKey());
  167. return null;
  168. }
  169. }
  170. );
  171. }
  172. public void testToConstructorBinding() {
  173. checkInjector(
  174. new AbstractModule() {
  175. protected void configure() {
  176. bind(D.class);
  177. }
  178. },
  179. new FailingElementVisitor() {
  180. @Override public <T> Void visit(Binding<T> binding) {
  181. assertTrue(binding instanceof ConstructorBinding);
  182. checkBindingSource(binding);
  183. assertEquals(Key.get(D.class), binding.getKey());
  184. binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
  185. @Override public Void visit(ConstructorBinding<? extends T> binding) {
  186. Constructor<?> expected = D.class.getDeclaredConstructors()[0];
  187. assertEquals(expected, binding.getConstructor().getMember());
  188. assertEquals(ImmutableSet.<InjectionPoint>of(), binding.getInjectableMembers());
  189. return null;
  190. }
  191. });
  192. return null;
  193. }
  194. }
  195. );
  196. }
  197. public void testConstantBinding() {
  198. checkInjector(
  199. new AbstractModule() {
  200. protected void configure() {
  201. bindConstant().annotatedWith(Names.named("one")).to(1);
  202. }
  203. },
  204. new FailingElementVisitor() {
  205. @Override public <T> Void visit(Binding<T> binding) {
  206. assertTrue(binding instanceof InstanceBinding);
  207. checkBindingSource(binding);
  208. assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
  209. binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
  210. @Override public Void visit(InstanceBinding<? extends T> binding) {
  211. assertEquals(1, binding.getInstance());
  212. return null;
  213. }
  214. });
  215. return null;
  216. }
  217. }
  218. );
  219. }
  220. public void testConvertedConstantBinding() {
  221. Injector injector = Guice.createInjector(new AbstractModule() {
  222. protected void configure() {
  223. bindConstant().annotatedWith(Names.named("one")).to("1");
  224. }
  225. });
  226. Binding<Integer> binding = injector.getBinding(Key.get(Integer.class, Names.named("one")));
  227. assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
  228. checkBindingSource(binding);
  229. assertTrue(binding instanceof ConvertedConstantBinding);
  230. binding.acceptTargetVisitor(new FailingTargetVisitor<Integer>() {
  231. @Override public Void visit(
  232. ConvertedConstantBinding<? extends Integer> binding) {
  233. assertEquals((Integer) 1, binding.getValue());
  234. assertEquals(Key.get(String.class, Names.named("one")), binding.getSourceKey());
  235. return null;
  236. }
  237. });
  238. }
  239. public void testProviderBinding() {
  240. Injector injector = Guice.createInjector(new AbstractModule() {
  241. protected void configure() {
  242. bind(String.class).toInstance("A");
  243. }
  244. });
  245. Key<Provider<String>> providerOfStringKey = new Key<Provider<String>>() {};
  246. Binding<Provider<String>> binding = injector.getBinding(providerOfStringKey);
  247. assertEquals(providerOfStringKey, binding.getKey());
  248. checkBindingSource(binding);
  249. assertTrue(binding instanceof ProviderBinding);
  250. binding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
  251. @Override public Void visit(
  252. ProviderBinding<? extends Provider<String>> binding) {
  253. assertEquals(Key.get(String.class), binding.getProvidedKey());
  254. return null;
  255. }
  256. });
  257. }
  258. public void testScopes() {
  259. checkInjector(
  260. new AbstractModule() {
  261. protected void configure() {
  262. bind(String.class).annotatedWith(Names.named("a"))
  263. .toProvider(StringProvider.class).in(Singleton.class);
  264. bind(String.class).annotatedWith(Names.named("b"))
  265. .toProvider(StringProvider.class).in(Scopes.SINGLETON);
  266. bind(String.class).annotatedWith(Names.named("c"))
  267. .toProvider(StringProvider.class).asEagerSingleton();
  268. bind(String.class).annotatedWith(Names.named("d"))
  269. .toProvider(StringProvider.class);
  270. }
  271. },
  272. new FailingElementVisitor() {
  273. @Override public <T> Void visit(Binding<T> command) {
  274. assertEquals(Key.get(String.class, Names.named("a")), command.getKey());
  275. command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
  276. @Override public Void visitScope(Scope scope) {
  277. // even though we bound with an annotation, the injector always uses instances
  278. assertSame(Scopes.SINGLETON, scope);
  279. return null;
  280. }
  281. });
  282. return null;
  283. }
  284. },
  285. new FailingElementVisitor() {
  286. @Override public <T> Void visit(Binding<T> command) {
  287. assertEquals(Key.get(String.class, Names.named("b")), command.getKey());
  288. command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
  289. @Override public Void visitScope(Scope scope) {
  290. assertSame(Scopes.SINGLETON, scope);
  291. return null;
  292. }
  293. });
  294. return null;
  295. }
  296. },
  297. new FailingElementVisitor() {
  298. @Override public <T> Void visit(Binding<T> command) {
  299. assertEquals(Key.get(String.class, Names.named("c")), command.getKey());
  300. command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
  301. @Override public Void visitEagerSingleton() {
  302. return null;
  303. }
  304. });
  305. return null;
  306. }
  307. },
  308. new FailingElementVisitor() {
  309. @Override public <T> Void visit(Binding<T> command) {
  310. assertEquals(Key.get(String.class, Names.named("d")), command.getKey());
  311. command.acceptScopingVisitor(new FailingBindingScopingVisitor() {
  312. @Override public Void visitNoScoping() {
  313. return null;
  314. }
  315. });
  316. return null;
  317. }
  318. }
  319. );
  320. }
  321. public void testExtensionSpi() {
  322. final AtomicBoolean visiting = new AtomicBoolean(false);
  323. final Injector injector = Guice.createInjector(new AbstractModule() {
  324. protected void configure() {
  325. bind(String.class).toProvider(new ProviderWithExtensionVisitor<String>() {
  326. public <B, V> V acceptExtensionVisitor(BindingTargetVisitor<B, V> visitor,
  327. ProviderInstanceBinding<? extends B> binding) {
  328. assertSame(this, binding.getUserSuppliedProvider());
  329. // We can't always check for FailingSpiTargetVisitor,
  330. // because constructing the injector visits here, and we need
  331. // to process the binding as normal
  332. if(visiting.get()) {
  333. assertTrue("visitor: " + visitor, visitor instanceof FailingSpiTargetVisitor);
  334. return (V)"visited";
  335. } else {
  336. return visitor.visit(binding);
  337. }
  338. }
  339. public String get() {
  340. return "FooBar";
  341. }
  342. });
  343. }
  344. });
  345. visiting.set(true);
  346. // Check for Provider<String> binding -- that is still a ProviderBinding.
  347. Key<Provider<String>> providerOfStringKey = new Key<Provider<String>>() {};
  348. Binding<Provider<String>> providerBinding = injector.getBinding(providerOfStringKey);
  349. assertEquals(providerOfStringKey, providerBinding.getKey());
  350. checkBindingSource(providerBinding);
  351. assertTrue("binding: " + providerBinding, providerBinding instanceof ProviderBinding);
  352. providerBinding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
  353. @Override public Void visit(ProviderBinding<? extends Provider<String>> binding) {
  354. assertEquals(Key.get(String.class), binding.getProvidedKey());
  355. return null;
  356. }
  357. });
  358. // Check for String binding -- that one is ProviderInstanceBinding, and gets hooked
  359. Binding<String> binding = injector.getBinding(String.class);
  360. assertEquals(Key.get(String.class), binding.getKey());
  361. checkBindingSource(binding);
  362. assertTrue(binding instanceof ProviderInstanceBinding);
  363. assertEquals("visited", binding.acceptTargetVisitor(new FailingSpiTargetVisitor<String>()));
  364. }
  365. private static class FailingSpiTargetVisitor<T> extends DefaultBindingTargetVisitor<T, String> {
  366. @Override
  367. protected String visitOther(Binding<? extends T> binding) {
  368. throw new AssertionFailedError();
  369. }
  370. }
  371. public void checkBindingSource(Binding binding) {
  372. assertContains(binding.getSource().toString(), getDeclaringSourcePart(getClass()));
  373. ElementSource source = (ElementSource) binding.getSource();
  374. assertFalse(source.getModuleClassNames().isEmpty());
  375. if (isIncludeStackTraceComplete()) {
  376. assertTrue(source.getStackTrace().length > 0);
  377. } else {
  378. assertEquals(0, source.getStackTrace().length);
  379. }
  380. }
  381. public void checkInjector(Module module, ElementVisitor<?>... visitors) {
  382. Injector injector = Guice.createInjector(module);
  383. List<Binding<?>> bindings = Lists.newArrayList(injector.getBindings().values());
  384. for (Iterator<Binding<?>> i = bindings.iterator(); i.hasNext(); ) {
  385. if (BUILT_IN_BINDINGS.contains(i.next().getKey())) {
  386. i.remove();
  387. }
  388. }
  389. Collections.sort(bindings, orderByKey);
  390. assertEquals(bindings.size(), visitors.length);
  391. for (int i = 0; i < visitors.length; i++) {
  392. ElementVisitor<?> visitor = visitors[i];
  393. Binding<?> binding = bindings.get(i);
  394. binding.acceptVisitor(visitor);
  395. }
  396. }
  397. private final ImmutableSet<Key<?>> BUILT_IN_BINDINGS = ImmutableSet.of(
  398. Key.get(Injector.class), Key.get(Stage.class), Key.get(Logger.class));
  399. private final Comparator<Binding<?>> orderByKey = new Comparator<Binding<?>>() {
  400. public int compare(Binding<?> a, Binding<?> b) {
  401. return a.getKey().toString().compareTo(b.getKey().toString());
  402. }
  403. };
  404. private static class StringProvider implements Provider<String> {
  405. public String get() {
  406. return "A";
  407. }
  408. }
  409. private static class C { }
  410. private static class D extends C {
  411. @Inject public D(Injector unused) { }
  412. }
  413. }