PageRenderTime 59ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/spice-inject/guice-patches/vanilla.test/com/google/inject/PrivateModuleTest.java

https://github.com/peterlynch/spice
Java | 449 lines | 361 code | 66 blank | 22 comment | 0 complexity | f73e65a16f7061ee989049792bdd4818 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;
  17. import static com.google.inject.Asserts.assertContains;
  18. import com.google.inject.internal.util.ImmutableSet;
  19. import com.google.inject.name.Named;
  20. import com.google.inject.name.Names;
  21. import static com.google.inject.name.Names.named;
  22. import com.google.inject.spi.Dependency;
  23. import com.google.inject.spi.ExposedBinding;
  24. import com.google.inject.spi.PrivateElements;
  25. import junit.framework.TestCase;
  26. /**
  27. * @author jessewilson@google.com (Jesse Wilson)
  28. */
  29. public class PrivateModuleTest extends TestCase {
  30. public void testBasicUsage() {
  31. Injector injector = Guice.createInjector(new AbstractModule() {
  32. protected void configure() {
  33. bind(String.class).annotatedWith(named("a")).toInstance("public");
  34. install(new PrivateModule() {
  35. public void configure() {
  36. bind(String.class).annotatedWith(named("b")).toInstance("i");
  37. bind(AB.class).annotatedWith(named("one")).to(AB.class);
  38. expose(AB.class).annotatedWith(named("one"));
  39. }
  40. });
  41. install(new PrivateModule() {
  42. public void configure() {
  43. bind(String.class).annotatedWith(named("b")).toInstance("ii");
  44. bind(AB.class).annotatedWith(named("two")).to(AB.class);
  45. expose(AB.class).annotatedWith(named("two"));
  46. }
  47. });
  48. }
  49. });
  50. AB ab1 = injector.getInstance(Key.get(AB.class, named("one")));
  51. assertEquals("public", ab1.a);
  52. assertEquals("i", ab1.b);
  53. AB ab2 = injector.getInstance(Key.get(AB.class, named("two")));
  54. assertEquals("public", ab2.a);
  55. assertEquals("ii", ab2.b);
  56. }
  57. public void testWithoutPrivateModules() {
  58. Injector injector = Guice.createInjector(new AbstractModule() {
  59. protected void configure() {
  60. PrivateBinder bindA = binder().newPrivateBinder();
  61. bindA.bind(String.class).annotatedWith(named("a")).toInstance("i");
  62. bindA.expose(String.class).annotatedWith(named("a"));
  63. bindA.bind(String.class).annotatedWith(named("c")).toInstance("private to A");
  64. PrivateBinder bindB = binder().newPrivateBinder();
  65. bindB.bind(String.class).annotatedWith(named("b")).toInstance("ii");
  66. bindB.expose(String.class).annotatedWith(named("b"));
  67. bindB.bind(String.class).annotatedWith(named("c")).toInstance("private to B");
  68. }
  69. });
  70. assertEquals("i", injector.getInstance(Key.get(String.class, named("a"))));
  71. assertEquals("ii", injector.getInstance(Key.get(String.class, named("b"))));
  72. }
  73. public void testMisplacedExposedAnnotation() {
  74. try {
  75. Guice.createInjector(new AbstractModule() {
  76. protected void configure() {}
  77. @Provides @Exposed
  78. String provideString() {
  79. return "i";
  80. }
  81. });
  82. fail();
  83. } catch (CreationException expected) {
  84. assertContains(expected.getMessage(), "Cannot expose java.lang.String on a standard binder. ",
  85. "Exposed bindings are only applicable to private binders.",
  86. " at " + PrivateModuleTest.class.getName(), "provideString(PrivateModuleTest.java:");
  87. }
  88. }
  89. public void testMisplacedExposeStatement() {
  90. try {
  91. Guice.createInjector(new AbstractModule() {
  92. protected void configure() {
  93. ((PrivateBinder) binder()).expose(String.class).annotatedWith(named("a"));
  94. }
  95. });
  96. fail();
  97. } catch (CreationException expected) {
  98. assertContains(expected.getMessage(), "Cannot expose java.lang.String on a standard binder. ",
  99. "Exposed bindings are only applicable to private binders.",
  100. " at " + PrivateModuleTest.class.getName(), "configure(PrivateModuleTest.java:");
  101. }
  102. }
  103. public void testPrivateModulesAndProvidesMethods() {
  104. Injector injector = Guice.createInjector(new AbstractModule() {
  105. protected void configure() {
  106. install(new PrivateModule() {
  107. public void configure() {
  108. expose(String.class).annotatedWith(named("a"));
  109. }
  110. @Provides @Named("a") String providePublicA() {
  111. return "i";
  112. }
  113. @Provides @Named("b") String providePrivateB() {
  114. return "private";
  115. }
  116. });
  117. install(new PrivateModule() {
  118. public void configure() {}
  119. @Provides @Named("c") String providePrivateC() {
  120. return "private";
  121. }
  122. @Provides @Exposed @Named("d") String providePublicD() {
  123. return "ii";
  124. }
  125. });
  126. }
  127. });
  128. assertEquals("i", injector.getInstance(Key.get(String.class, named("a"))));
  129. try {
  130. injector.getInstance(Key.get(String.class, named("b")));
  131. fail();
  132. } catch(ConfigurationException expected) {
  133. }
  134. try {
  135. injector.getInstance(Key.get(String.class, named("c")));
  136. fail();
  137. } catch(ConfigurationException expected) {
  138. }
  139. assertEquals("ii", injector.getInstance(Key.get(String.class, named("d"))));
  140. }
  141. public void testCannotBindAKeyExportedByASibling() {
  142. try {
  143. Guice.createInjector(new AbstractModule() {
  144. protected void configure() {
  145. install(new PrivateModule() {
  146. public void configure() {
  147. bind(String.class).toInstance("public");
  148. expose(String.class);
  149. }
  150. });
  151. install(new PrivateModule() {
  152. public void configure() {
  153. bind(String.class).toInstance("private");
  154. }
  155. });
  156. }
  157. });
  158. fail();
  159. } catch (CreationException expected) {
  160. assertContains(expected.getMessage(),
  161. "A binding to java.lang.String was already configured at ",
  162. getClass().getName(), ".configure(PrivateModuleTest.java:",
  163. " at " + getClass().getName(), ".configure(PrivateModuleTest.java:");
  164. }
  165. }
  166. public void testExposeButNoBind() {
  167. try {
  168. Guice.createInjector(new AbstractModule() {
  169. protected void configure() {
  170. bind(String.class).annotatedWith(named("a")).toInstance("a");
  171. bind(String.class).annotatedWith(named("b")).toInstance("b");
  172. install(new PrivateModule() {
  173. public void configure() {
  174. expose(AB.class);
  175. }
  176. });
  177. }
  178. });
  179. fail("AB was exposed but not bound");
  180. } catch (CreationException expected) {
  181. assertContains(expected.getMessage(),
  182. "Could not expose() " + AB.class.getName() + ", it must be explicitly bound",
  183. ".configure(PrivateModuleTest.java:");
  184. }
  185. }
  186. /**
  187. * Ensure that when we've got errors in different private modules, Guice presents all errors
  188. * in a unified message.
  189. */
  190. public void testMessagesFromPrivateModulesAreNicelyIntegrated() {
  191. try {
  192. Guice.createInjector(
  193. new PrivateModule() {
  194. public void configure() {
  195. bind(C.class);
  196. }
  197. },
  198. new PrivateModule() {
  199. public void configure() {
  200. bind(AB.class);
  201. }
  202. }
  203. );
  204. fail();
  205. } catch (CreationException expected) {
  206. assertContains(expected.getMessage(),
  207. "1) No implementation for " + C.class.getName() + " was bound.",
  208. "at " + getClass().getName(), ".configure(PrivateModuleTest.java:",
  209. "2) No implementation for " + String.class.getName(), "Named(value=a) was bound.",
  210. "for field at " + AB.class.getName() + ".a(PrivateModuleTest.java:",
  211. "3) No implementation for " + String.class.getName(), "Named(value=b) was bound.",
  212. "for field at " + AB.class.getName() + ".b(PrivateModuleTest.java:",
  213. "3 errors");
  214. }
  215. }
  216. public void testNestedPrivateInjectors() {
  217. Injector injector = Guice.createInjector(new PrivateModule() {
  218. public void configure() {
  219. expose(String.class);
  220. install(new PrivateModule() {
  221. public void configure() {
  222. bind(String.class).toInstance("nested");
  223. expose(String.class);
  224. }
  225. });
  226. }
  227. });
  228. assertEquals("nested", injector.getInstance(String.class));
  229. }
  230. public void testInstallingRegularModulesFromPrivateModules() {
  231. Injector injector = Guice.createInjector(new PrivateModule() {
  232. public void configure() {
  233. expose(String.class);
  234. install(new AbstractModule() {
  235. protected void configure() {
  236. bind(String.class).toInstance("nested");
  237. }
  238. });
  239. }
  240. });
  241. assertEquals("nested", injector.getInstance(String.class));
  242. }
  243. public void testNestedPrivateModulesWithSomeKeysUnexposed() {
  244. Injector injector = Guice.createInjector(new PrivateModule() {
  245. public void configure() {
  246. bind(String.class).annotatedWith(named("bound outer, exposed outer")).toInstance("boeo");
  247. expose(String.class).annotatedWith(named("bound outer, exposed outer"));
  248. bind(String.class).annotatedWith(named("bound outer, exposed none")).toInstance("boen");
  249. expose(String.class).annotatedWith(named("bound inner, exposed both"));
  250. install(new PrivateModule() {
  251. public void configure() {
  252. bind(String.class).annotatedWith(named("bound inner, exposed both")).toInstance("bieb");
  253. expose(String.class).annotatedWith(named("bound inner, exposed both"));
  254. bind(String.class).annotatedWith(named("bound inner, exposed none")).toInstance("bien");
  255. }
  256. });
  257. }
  258. });
  259. assertEquals("boeo",
  260. injector.getInstance(Key.get(String.class, named("bound outer, exposed outer"))));
  261. assertEquals("bieb",
  262. injector.getInstance(Key.get(String.class, named("bound inner, exposed both"))));
  263. try {
  264. injector.getInstance(Key.get(String.class, named("bound outer, exposed none")));
  265. fail();
  266. } catch (ConfigurationException expected) {
  267. }
  268. try {
  269. injector.getInstance(Key.get(String.class, named("bound inner, exposed none")));
  270. fail();
  271. } catch (ConfigurationException expected) {
  272. }
  273. }
  274. public void testDependenciesBetweenPrivateAndPublic() {
  275. Injector injector = Guice.createInjector(
  276. new PrivateModule() {
  277. protected void configure() {}
  278. @Provides @Exposed @Named("a") String provideA() {
  279. return "A";
  280. }
  281. @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) {
  282. return ab + "C";
  283. }
  284. },
  285. new AbstractModule() {
  286. protected void configure() {}
  287. @Provides @Named("ab") String provideAb(@Named("a") String a) {
  288. return a + "B";
  289. }
  290. @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) {
  291. return abc + "D";
  292. }
  293. }
  294. );
  295. assertEquals("ABCD", injector.getInstance(Key.get(String.class, named("abcd"))));
  296. }
  297. public void testDependenciesBetweenPrivateAndPublicWithPublicEagerSingleton() {
  298. Injector injector = Guice.createInjector(
  299. new PrivateModule() {
  300. protected void configure() {}
  301. @Provides @Exposed @Named("a") String provideA() {
  302. return "A";
  303. }
  304. @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) {
  305. return ab + "C";
  306. }
  307. },
  308. new AbstractModule() {
  309. protected void configure() {
  310. bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider<String>() {
  311. @Inject @Named("abcd") String abcd;
  312. public String get() {
  313. return abcd + "E";
  314. }
  315. }).asEagerSingleton();
  316. }
  317. @Provides @Named("ab") String provideAb(@Named("a") String a) {
  318. return a + "B";
  319. }
  320. @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) {
  321. return abc + "D";
  322. }
  323. }
  324. );
  325. assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde"))));
  326. }
  327. public void testDependenciesBetweenPrivateAndPublicWithPrivateEagerSingleton() {
  328. Injector injector = Guice.createInjector(
  329. new AbstractModule() {
  330. protected void configure() {}
  331. @Provides @Named("ab") String provideAb(@Named("a") String a) {
  332. return a + "B";
  333. }
  334. @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) {
  335. return abc + "D";
  336. }
  337. },
  338. new PrivateModule() {
  339. protected void configure() {
  340. bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider<String>() {
  341. @Inject @Named("abcd") String abcd;
  342. public String get() {
  343. return abcd + "E";
  344. }
  345. }).asEagerSingleton();
  346. expose(String.class).annotatedWith(named("abcde"));
  347. }
  348. @Provides @Exposed @Named("a") String provideA() {
  349. return "A";
  350. }
  351. @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) {
  352. return ab + "C";
  353. }
  354. }
  355. );
  356. assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde"))));
  357. }
  358. static class AB {
  359. @Inject @Named("a") String a;
  360. @Inject @Named("b") String b;
  361. }
  362. interface C {}
  363. public void testSpiAccess() {
  364. Injector injector = Guice.createInjector(new PrivateModule() {
  365. public void configure() {
  366. bind(String.class).annotatedWith(named("a")).toInstance("private");
  367. bind(String.class).annotatedWith(named("b")).toInstance("exposed");
  368. expose(String.class).annotatedWith(named("b"));
  369. }
  370. });
  371. ExposedBinding<?> binding
  372. = (ExposedBinding<?>) injector.getBinding(Key.get(String.class, Names.named("b")));
  373. assertEquals(ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class))),
  374. binding.getDependencies());
  375. PrivateElements privateElements = binding.getPrivateElements();
  376. assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class, named("b"))),
  377. privateElements.getExposedKeys());
  378. assertContains(privateElements.getExposedSource(Key.get(String.class, named("b"))).toString(),
  379. PrivateModuleTest.class.getName(), ".configure(PrivateModuleTest.java:");
  380. Injector privateInjector = privateElements.getInjector();
  381. assertEquals("private", privateInjector.getInstance(Key.get(String.class, Names.named("a"))));
  382. }
  383. }