PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java

https://gitlab.com/metamorphiccode/guice
Java | 1486 lines | 1259 code | 193 blank | 34 comment | 28 complexity | dc0387f6fab96c410a39803f05a1450d MD5 | raw file
  1. /**
  2. * Copyright (C) 2007 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.throwingproviders;
  17. import static java.lang.annotation.ElementType.METHOD;
  18. import static java.lang.annotation.RetentionPolicy.RUNTIME;
  19. import com.google.common.base.Function;
  20. import com.google.common.collect.ImmutableList;
  21. import com.google.common.collect.ImmutableSet;
  22. import com.google.common.collect.Iterables;
  23. import com.google.common.collect.Lists;
  24. import com.google.inject.AbstractModule;
  25. import com.google.inject.Asserts;
  26. import com.google.inject.BindingAnnotation;
  27. import com.google.inject.CreationException;
  28. import com.google.inject.Guice;
  29. import com.google.inject.Inject;
  30. import com.google.inject.Injector;
  31. import com.google.inject.Key;
  32. import com.google.inject.OutOfScopeException;
  33. import com.google.inject.Provider;
  34. import com.google.inject.ProvisionException;
  35. import com.google.inject.Scope;
  36. import com.google.inject.ScopeAnnotation;
  37. import com.google.inject.TypeLiteral;
  38. import com.google.inject.internal.util.Classes;
  39. import com.google.inject.name.Named;
  40. import com.google.inject.name.Names;
  41. import com.google.inject.spi.Dependency;
  42. import com.google.inject.spi.HasDependencies;
  43. import com.google.inject.spi.Message;
  44. import com.google.inject.throwingproviders.ThrowingProviderBinder.Result;
  45. import junit.framework.TestCase;
  46. import java.io.IOException;
  47. import java.lang.annotation.Annotation;
  48. import java.lang.annotation.ElementType;
  49. import java.lang.annotation.Retention;
  50. import java.lang.annotation.RetentionPolicy;
  51. import java.lang.annotation.Target;
  52. import java.net.BindException;
  53. import java.rmi.AccessException;
  54. import java.rmi.RemoteException;
  55. import java.util.ArrayList;
  56. import java.util.Arrays;
  57. import java.util.List;
  58. import java.util.Set;
  59. import java.util.TooManyListenersException;
  60. /**
  61. * @author jmourits@google.com (Jerome Mourits)
  62. * @author jessewilson@google.com (Jesse Wilson)
  63. * @author sameb@google.com (Sam Berlin)
  64. */
  65. public class CheckedProviderTest extends TestCase {
  66. @Target(METHOD) @Retention(RUNTIME) @BindingAnnotation
  67. @interface NotExceptionScoping { };
  68. private static final Function<Dependency<?>, Key<?>> DEPENDENCY_TO_KEY =
  69. new Function<Dependency<?>, Key<?>>() {
  70. public Key<?> apply(Dependency<?> from) {
  71. return from.getKey();
  72. }
  73. };
  74. private final TypeLiteral<RemoteProvider<Foo>> remoteProviderOfFoo
  75. = new TypeLiteral<RemoteProvider<Foo>>() { };
  76. private final MockRemoteProvider<Foo> mockRemoteProvider = new MockRemoteProvider<Foo>();
  77. private final TestScope testScope = new TestScope();
  78. private Injector bindInjector;
  79. private Injector providesInjector;
  80. private Injector cxtorInjector;
  81. @Override
  82. protected void setUp() throws Exception {
  83. MockFoo.nextToThrow = null;
  84. MockFoo.nextToReturn = null;
  85. AnotherMockFoo.nextToThrow = null;
  86. AnotherMockFoo.nextToReturn = null;
  87. bindInjector = Guice.createInjector(new AbstractModule() {
  88. @Override
  89. protected void configure() {
  90. ThrowingProviderBinder.create(binder())
  91. .bind(RemoteProvider.class, Foo.class)
  92. .to(mockRemoteProvider)
  93. .in(testScope);
  94. ThrowingProviderBinder.create(binder())
  95. .bind(RemoteProvider.class, Foo.class)
  96. .annotatedWith(NotExceptionScoping.class)
  97. .scopeExceptions(false)
  98. .to(mockRemoteProvider)
  99. .in(testScope);
  100. }
  101. });
  102. providesInjector = Guice.createInjector(new AbstractModule() {
  103. @Override
  104. protected void configure() {
  105. install(ThrowingProviderBinder.forModule(this));
  106. bindScope(TestScope.Scoped.class, testScope);
  107. }
  108. @SuppressWarnings("unused")
  109. @CheckedProvides(RemoteProvider.class)
  110. @TestScope.Scoped
  111. Foo throwOrGet() throws RemoteException, BindException {
  112. return mockRemoteProvider.get();
  113. }
  114. @SuppressWarnings("unused")
  115. @CheckedProvides(value = RemoteProvider.class, scopeExceptions = false)
  116. @NotExceptionScoping
  117. @TestScope.Scoped
  118. Foo notExceptionScopingThrowOrGet() throws RemoteException, BindException {
  119. return mockRemoteProvider.get();
  120. }
  121. });
  122. cxtorInjector = Guice.createInjector(new AbstractModule() {
  123. @Override
  124. protected void configure() {
  125. ThrowingProviderBinder.create(binder())
  126. .bind(RemoteProvider.class, Foo.class)
  127. .providing(MockFoo.class)
  128. .in(testScope);
  129. ThrowingProviderBinder.create(binder())
  130. .bind(RemoteProvider.class, Foo.class)
  131. .annotatedWith(NotExceptionScoping.class)
  132. .scopeExceptions(false)
  133. .providing(MockFoo.class)
  134. .in(testScope);
  135. }
  136. });
  137. }
  138. public void testExceptionsThrown_Bind() throws Exception {
  139. tExceptionsThrown(bindInjector);
  140. }
  141. public void testExceptionsThrown_Provides() throws Exception {
  142. tExceptionsThrown(providesInjector);
  143. }
  144. public void testExceptionsThrown_Cxtor() throws Exception {
  145. tExceptionsThrown(cxtorInjector);
  146. }
  147. private void tExceptionsThrown(Injector injector) throws Exception {
  148. RemoteProvider<Foo> remoteProvider =
  149. injector.getInstance(Key.get(remoteProviderOfFoo));
  150. mockRemoteProvider.throwOnNextGet(new BindException("kaboom!"));
  151. MockFoo.nextToThrow = new BindException("kaboom!");
  152. try {
  153. remoteProvider.get();
  154. fail();
  155. } catch (BindException expected) {
  156. assertEquals("kaboom!", expected.getMessage());
  157. }
  158. }
  159. public void testValuesScoped_Bind() throws Exception {
  160. tValuesScoped(bindInjector, null);
  161. }
  162. public void testValuesScoped_Provides() throws Exception {
  163. tValuesScoped(providesInjector, null);
  164. }
  165. public void testValuesScopedWhenNotExceptionScoping_Bind() throws Exception {
  166. tValuesScoped(bindInjector, NotExceptionScoping.class);
  167. }
  168. public void testValuesScopedWhenNotExceptionScoping_Provides() throws Exception {
  169. tValuesScoped(providesInjector, NotExceptionScoping.class);
  170. }
  171. private void tValuesScoped(Injector injector,
  172. Class<? extends Annotation> annotation) throws Exception {
  173. Key<RemoteProvider<Foo>> key = annotation != null ?
  174. Key.get(remoteProviderOfFoo, annotation) :
  175. Key.get(remoteProviderOfFoo);
  176. RemoteProvider<Foo> remoteProvider = injector.getInstance(key);
  177. mockRemoteProvider.setNextToReturn(new SimpleFoo("A"));
  178. assertEquals("A", remoteProvider.get().s());
  179. mockRemoteProvider.setNextToReturn(new SimpleFoo("B"));
  180. assertEquals("A", remoteProvider.get().s());
  181. testScope.beginNewScope();
  182. assertEquals("B", remoteProvider.get().s());
  183. }
  184. public void testValuesScoped_Cxtor() throws Exception {
  185. RemoteProvider<Foo> remoteProvider =
  186. cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
  187. Foo retrieved = remoteProvider.get();
  188. assertSame(retrieved, remoteProvider.get()); // same, not in new scope.
  189. testScope.beginNewScope();
  190. assertNotSame(retrieved, remoteProvider.get()); // different, new scope.
  191. }
  192. public void testExceptionsScoped_Bind() throws Exception {
  193. tExceptionsScoped(bindInjector);
  194. }
  195. public void testExceptionsScoped_Provides() throws Exception {
  196. tExceptionsScoped(providesInjector);
  197. }
  198. public void testExceptionScopes_Cxtor() throws Exception {
  199. tExceptionsScoped(cxtorInjector);
  200. }
  201. private void tExceptionsScoped(Injector injector) throws Exception {
  202. RemoteProvider<Foo> remoteProvider =
  203. injector.getInstance(Key.get(remoteProviderOfFoo));
  204. mockRemoteProvider.throwOnNextGet(new RemoteException("A"));
  205. MockFoo.nextToThrow = new RemoteException("A");
  206. try {
  207. remoteProvider.get();
  208. fail();
  209. } catch (RemoteException expected) {
  210. assertEquals("A", expected.getMessage());
  211. }
  212. mockRemoteProvider.throwOnNextGet(new RemoteException("B"));
  213. MockFoo.nextToThrow = new RemoteException("B");
  214. try {
  215. remoteProvider.get();
  216. fail();
  217. } catch (RemoteException expected) {
  218. assertEquals("A", expected.getMessage());
  219. }
  220. }
  221. public void testExceptionsNotScopedWhenNotExceptionScoping_Bind() throws Exception {
  222. tExceptionsNotScopedWhenNotExceptionScoping(bindInjector);
  223. }
  224. public void testExceptionsNotScopedWhenNotExceptionScoping_Provides() throws Exception {
  225. tExceptionsNotScopedWhenNotExceptionScoping(providesInjector);
  226. }
  227. public void testExceptionNotScopedWhenNotExceptionScoping_Cxtor() throws Exception {
  228. tExceptionsNotScopedWhenNotExceptionScoping(cxtorInjector);
  229. }
  230. private void tExceptionsNotScopedWhenNotExceptionScoping(Injector injector) throws Exception {
  231. RemoteProvider<Foo> remoteProvider =
  232. injector.getInstance(Key.get(remoteProviderOfFoo, NotExceptionScoping.class));
  233. mockRemoteProvider.throwOnNextGet(new RemoteException("A"));
  234. MockFoo.nextToThrow = new RemoteException("A");
  235. try {
  236. remoteProvider.get();
  237. fail();
  238. } catch (RemoteException expected) {
  239. assertEquals("A", expected.getMessage());
  240. }
  241. mockRemoteProvider.throwOnNextGet(new RemoteException("B"));
  242. MockFoo.nextToThrow = new RemoteException("B");
  243. try {
  244. remoteProvider.get();
  245. fail();
  246. } catch (RemoteException expected) {
  247. assertEquals("B", expected.getMessage());
  248. }
  249. }
  250. public void testAnnotations_Bind() throws Exception {
  251. final MockRemoteProvider<Foo> mockRemoteProviderA = new MockRemoteProvider<Foo>();
  252. final MockRemoteProvider<Foo> mockRemoteProviderB = new MockRemoteProvider<Foo>();
  253. bindInjector = Guice.createInjector(new AbstractModule() {
  254. @Override
  255. protected void configure() {
  256. ThrowingProviderBinder.create(binder())
  257. .bind(RemoteProvider.class, Foo.class)
  258. .annotatedWith(Names.named("a"))
  259. .to(mockRemoteProviderA);
  260. ThrowingProviderBinder.create(binder())
  261. .bind(RemoteProvider.class, Foo.class)
  262. .to(mockRemoteProviderB);
  263. }
  264. });
  265. tAnnotations(bindInjector, mockRemoteProviderA, mockRemoteProviderB);
  266. }
  267. public void testAnnotations_Provides() throws Exception {
  268. final MockRemoteProvider<Foo> mockRemoteProviderA = new MockRemoteProvider<Foo>();
  269. final MockRemoteProvider<Foo> mockRemoteProviderB = new MockRemoteProvider<Foo>();
  270. providesInjector = Guice.createInjector(new AbstractModule() {
  271. @Override
  272. protected void configure() {
  273. install(ThrowingProviderBinder.forModule(this));
  274. }
  275. @SuppressWarnings("unused")
  276. @CheckedProvides(RemoteProvider.class)
  277. @Named("a")
  278. Foo throwOrGet() throws RemoteException, BindException {
  279. return mockRemoteProviderA.get();
  280. }
  281. @SuppressWarnings("unused")
  282. @CheckedProvides(RemoteProvider.class)
  283. Foo throwOrGet2() throws RemoteException, BindException {
  284. return mockRemoteProviderB.get();
  285. }
  286. });
  287. tAnnotations(providesInjector, mockRemoteProviderA, mockRemoteProviderB);
  288. }
  289. private void tAnnotations(Injector injector, MockRemoteProvider<Foo> mockA,
  290. MockRemoteProvider<Foo> mockB) throws Exception {
  291. mockA.setNextToReturn(new SimpleFoo("A"));
  292. mockB.setNextToReturn(new SimpleFoo("B"));
  293. assertEquals("A",
  294. injector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s());
  295. assertEquals("B",
  296. injector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
  297. }
  298. public void testAnnotations_Cxtor() throws Exception {
  299. cxtorInjector = Guice.createInjector(new AbstractModule() {
  300. @Override
  301. protected void configure() {
  302. ThrowingProviderBinder.create(binder())
  303. .bind(RemoteProvider.class, Foo.class)
  304. .annotatedWith(Names.named("a"))
  305. .providing(MockFoo.class);
  306. ThrowingProviderBinder.create(binder())
  307. .bind(RemoteProvider.class, Foo.class)
  308. .providing(AnotherMockFoo.class);
  309. }
  310. });
  311. MockFoo.nextToReturn = "A";
  312. AnotherMockFoo.nextToReturn = "B";
  313. assertEquals("A",
  314. cxtorInjector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s());
  315. assertEquals("B",
  316. cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
  317. }
  318. public void testUndeclaredExceptions_Bind() throws Exception {
  319. tUndeclaredExceptions(bindInjector);
  320. }
  321. public void testUndeclaredExceptions_Provides() throws Exception {
  322. tUndeclaredExceptions(providesInjector);
  323. }
  324. public void testUndeclaredExceptions_Cxtor() throws Exception {
  325. tUndeclaredExceptions(cxtorInjector);
  326. }
  327. private void tUndeclaredExceptions(Injector injector) throws Exception {
  328. RemoteProvider<Foo> remoteProvider =
  329. injector.getInstance(Key.get(remoteProviderOfFoo));
  330. mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("A"));
  331. MockFoo.nextToThrow = new IndexOutOfBoundsException("A");
  332. try {
  333. remoteProvider.get();
  334. fail();
  335. } catch (RuntimeException e) {
  336. assertEquals("A", e.getCause().getMessage());
  337. }
  338. // undeclared exceptions shouldn't be scoped
  339. mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("B"));
  340. MockFoo.nextToThrow = new IndexOutOfBoundsException("B");
  341. try {
  342. remoteProvider.get();
  343. fail();
  344. } catch (RuntimeException e) {
  345. assertEquals("B", e.getCause().getMessage());
  346. }
  347. }
  348. public void testThrowingProviderSubclassing() throws Exception {
  349. final SubMockRemoteProvider aProvider = new SubMockRemoteProvider();
  350. aProvider.setNextToReturn(new SimpleFoo("A"));
  351. bindInjector = Guice.createInjector(new AbstractModule() {
  352. @Override
  353. protected void configure() {
  354. ThrowingProviderBinder.create(binder())
  355. .bind(RemoteProvider.class, Foo.class)
  356. .to(aProvider);
  357. }
  358. });
  359. assertEquals("A",
  360. bindInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
  361. }
  362. static class SubMockRemoteProvider extends MockRemoteProvider<Foo> { }
  363. public void testBindingToNonInterfaceType_Bind() throws Exception {
  364. try {
  365. Guice.createInjector(new AbstractModule() {
  366. @Override
  367. protected void configure() {
  368. ThrowingProviderBinder.create(binder())
  369. .bind(MockRemoteProvider.class, Foo.class)
  370. .to(mockRemoteProvider);
  371. }
  372. });
  373. fail();
  374. } catch (CreationException expected) {
  375. assertEquals(MockRemoteProvider.class.getName() + " must be an interface",
  376. Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
  377. }
  378. }
  379. public void testBindingToNonInterfaceType_Provides() throws Exception {
  380. try {
  381. Guice.createInjector(new AbstractModule() {
  382. @Override
  383. protected void configure() {
  384. install(ThrowingProviderBinder.forModule(this));
  385. }
  386. @SuppressWarnings("unused")
  387. @CheckedProvides(MockRemoteProvider.class)
  388. Foo foo() {
  389. return null;
  390. }
  391. });
  392. fail();
  393. } catch (CreationException expected) {
  394. assertEquals(MockRemoteProvider.class.getName() + " must be an interface",
  395. Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
  396. }
  397. }
  398. public void testBindingToSubSubInterface_Bind() throws Exception {
  399. try {
  400. bindInjector = Guice.createInjector(new AbstractModule() {
  401. @Override
  402. protected void configure() {
  403. ThrowingProviderBinder.create(binder())
  404. .bind(SubRemoteProvider.class, Foo.class);
  405. }
  406. });
  407. fail();
  408. } catch (CreationException expected) {
  409. assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)",
  410. Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
  411. }
  412. }
  413. public void testBindingToSubSubInterface_Provides() throws Exception {
  414. try {
  415. Guice.createInjector(new AbstractModule() {
  416. @Override
  417. protected void configure() {
  418. install(ThrowingProviderBinder.forModule(this));
  419. }
  420. @SuppressWarnings("unused")
  421. @CheckedProvides(SubRemoteProvider.class)
  422. Foo foo() {
  423. return null;
  424. }
  425. });
  426. fail();
  427. } catch (CreationException expected) {
  428. assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)",
  429. Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
  430. }
  431. }
  432. interface SubRemoteProvider extends RemoteProvider<String> { }
  433. public void testBindingToInterfaceWithExtraMethod_Bind() throws Exception {
  434. try {
  435. bindInjector = Guice.createInjector(new AbstractModule() {
  436. @Override
  437. protected void configure() {
  438. ThrowingProviderBinder.create(binder())
  439. .bind(RemoteProviderWithExtraMethod.class, Foo.class);
  440. }
  441. });
  442. fail();
  443. } catch (CreationException expected) {
  444. assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared "
  445. + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(),
  446. Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
  447. }
  448. }
  449. public void testBindingToInterfaceWithExtraMethod_Provides() throws Exception {
  450. try {
  451. Guice.createInjector(new AbstractModule() {
  452. @Override
  453. protected void configure() {
  454. install(ThrowingProviderBinder.forModule(this));
  455. }
  456. @SuppressWarnings("unused")
  457. @CheckedProvides(RemoteProviderWithExtraMethod.class)
  458. Foo foo() {
  459. return null;
  460. }
  461. });
  462. fail();
  463. } catch (CreationException expected) {
  464. assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared "
  465. + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(),
  466. Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
  467. }
  468. }
  469. public void testDependencies_Bind() {
  470. bindInjector = Guice.createInjector(new AbstractModule() {
  471. @Override
  472. protected void configure() {
  473. bind(String.class).toInstance("Foo");
  474. bind(Integer.class).toInstance(5);
  475. bind(Double.class).toInstance(5d);
  476. bind(Long.class).toInstance(5L);
  477. ThrowingProviderBinder.create(binder())
  478. .bind(RemoteProvider.class, Foo.class)
  479. .to(DependentRemoteProvider.class);
  480. }
  481. });
  482. HasDependencies hasDependencies =
  483. (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfFoo));
  484. hasDependencies =
  485. (HasDependencies)bindInjector.getBinding(
  486. Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
  487. // Make sure that that is dependent on DependentRemoteProvider.
  488. assertEquals(Dependency.get(Key.get(DependentRemoteProvider.class)),
  489. Iterables.getOnlyElement(hasDependencies.getDependencies()));
  490. // And make sure DependentRemoteProvider has the proper dependencies.
  491. hasDependencies = (HasDependencies)bindInjector.getBinding(DependentRemoteProvider.class);
  492. Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
  493. Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
  494. assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
  495. Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
  496. }
  497. public void testDependencies_Provides() {
  498. providesInjector = Guice.createInjector(new AbstractModule() {
  499. @Override
  500. protected void configure() {
  501. bind(String.class).toInstance("Foo");
  502. bind(Integer.class).toInstance(5);
  503. bind(Double.class).toInstance(5d);
  504. bind(Long.class).toInstance(5L);
  505. install(ThrowingProviderBinder.forModule(this));
  506. }
  507. @SuppressWarnings("unused")
  508. @CheckedProvides(RemoteProvider.class)
  509. Foo foo(String s, Integer i, Double d, Long l) {
  510. return null;
  511. }
  512. });
  513. HasDependencies hasDependencies =
  514. (HasDependencies) providesInjector.getBinding(Key.get(remoteProviderOfFoo));
  515. // RemoteProvider<String> is dependent on the provider method..
  516. hasDependencies = (HasDependencies) providesInjector.getBinding(
  517. Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
  518. // And the provider method has our real dependencies..
  519. hasDependencies = (HasDependencies)providesInjector.getBinding(
  520. Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
  521. Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
  522. Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
  523. assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
  524. Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
  525. }
  526. public void testDependencies_Cxtor() {
  527. cxtorInjector = Guice.createInjector(new AbstractModule() {
  528. @Override
  529. protected void configure() {
  530. bind(String.class).toInstance("Foo");
  531. bind(Integer.class).toInstance(5);
  532. bind(Double.class).toInstance(5d);
  533. bind(Long.class).toInstance(5L);
  534. ThrowingProviderBinder.create(binder())
  535. .bind(RemoteProvider.class, Foo.class)
  536. .providing(DependentMockFoo.class);
  537. }
  538. });
  539. Key<?> key = Key.get(remoteProviderOfFoo);
  540. // RemoteProvider<String> is dependent on Result.
  541. HasDependencies hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
  542. key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
  543. assertEquals(Result.class, key.getTypeLiteral().getRawType());
  544. // Result is dependent on the fake CheckedProvider impl
  545. hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
  546. key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
  547. assertTrue(CheckedProvider.class.isAssignableFrom(key.getTypeLiteral().getRawType()));
  548. // And the CheckedProvider is dependent on DependentMockFoo...
  549. hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
  550. key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
  551. assertEquals(DependentMockFoo.class, key.getTypeLiteral().getRawType());
  552. // And DependentMockFoo is dependent on the goods.
  553. hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
  554. Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
  555. Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
  556. assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
  557. Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
  558. }
  559. interface RemoteProviderWithExtraMethod<T> extends CheckedProvider<T> {
  560. T get(T defaultValue) throws RemoteException, BindException;
  561. }
  562. interface RemoteProvider<T> extends CheckedProvider<T> {
  563. public T get() throws RemoteException, BindException;
  564. }
  565. static class DependentMockFoo implements Foo {
  566. @Inject double foo;
  567. @ThrowingInject public DependentMockFoo(String foo, int bar) {
  568. }
  569. @Inject void initialize(long foo) {}
  570. @Override
  571. public String s() {
  572. return null;
  573. }
  574. }
  575. static class DependentRemoteProvider<T> implements RemoteProvider<T> {
  576. @Inject double foo;
  577. @Inject public DependentRemoteProvider(String foo, int bar) {
  578. }
  579. @Inject void initialize(long foo) {}
  580. public T get() {
  581. return null;
  582. }
  583. }
  584. interface Foo {
  585. String s();
  586. }
  587. static class SimpleFoo implements Foo {
  588. private String s;
  589. SimpleFoo(String s) {
  590. this.s = s;
  591. }
  592. @Override
  593. public String s() {
  594. return s;
  595. }
  596. @Override
  597. public String toString() {
  598. return s;
  599. }
  600. }
  601. static class MockFoo implements Foo {
  602. static Exception nextToThrow;
  603. static String nextToReturn;
  604. @ThrowingInject
  605. MockFoo() throws RemoteException, BindException {
  606. if (nextToThrow instanceof RemoteException) {
  607. throw (RemoteException) nextToThrow;
  608. } else if (nextToThrow instanceof BindException) {
  609. throw (BindException) nextToThrow;
  610. } else if (nextToThrow instanceof RuntimeException) {
  611. throw (RuntimeException) nextToThrow;
  612. } else if (nextToThrow == null) {
  613. // Do nothing, return this.
  614. } else {
  615. throw new AssertionError("nextToThrow must be a runtime or remote exception");
  616. }
  617. }
  618. @Override
  619. public String s() {
  620. return nextToReturn;
  621. }
  622. @Override
  623. public String toString() {
  624. return nextToReturn;
  625. }
  626. }
  627. static class AnotherMockFoo implements Foo {
  628. static Exception nextToThrow;
  629. static String nextToReturn;
  630. @ThrowingInject
  631. AnotherMockFoo() throws RemoteException, BindException {
  632. if (nextToThrow instanceof RemoteException) {
  633. throw (RemoteException) nextToThrow;
  634. } else if (nextToThrow instanceof BindException) {
  635. throw (BindException) nextToThrow;
  636. } else if (nextToThrow instanceof RuntimeException) {
  637. throw (RuntimeException) nextToThrow;
  638. } else if (nextToThrow == null) {
  639. // Do nothing, return this.
  640. } else {
  641. throw new AssertionError("nextToThrow must be a runtime or remote exception");
  642. }
  643. }
  644. @Override
  645. public String s() {
  646. return nextToReturn;
  647. }
  648. @Override
  649. public String toString() {
  650. return nextToReturn;
  651. }
  652. }
  653. static class MockRemoteProvider<T> implements RemoteProvider<T> {
  654. Exception nextToThrow;
  655. T nextToReturn;
  656. public void throwOnNextGet(Exception nextToThrow) {
  657. this.nextToThrow = nextToThrow;
  658. }
  659. public void setNextToReturn(T nextToReturn) {
  660. this.nextToReturn = nextToReturn;
  661. }
  662. public T get() throws RemoteException, BindException {
  663. if (nextToThrow instanceof RemoteException) {
  664. throw (RemoteException) nextToThrow;
  665. } else if (nextToThrow instanceof BindException) {
  666. throw (BindException) nextToThrow;
  667. } else if (nextToThrow instanceof RuntimeException) {
  668. throw (RuntimeException) nextToThrow;
  669. } else if (nextToThrow == null) {
  670. return nextToReturn;
  671. } else {
  672. throw new AssertionError("nextToThrow must be a runtime or remote exception");
  673. }
  674. }
  675. }
  676. public void testBindingToInterfaceWithBoundValueType_Bind() throws RemoteException {
  677. bindInjector = Guice.createInjector(new AbstractModule() {
  678. @Override
  679. protected void configure() {
  680. ThrowingProviderBinder.create(binder())
  681. .bind(StringRemoteProvider.class, String.class)
  682. .to(new StringRemoteProvider() {
  683. public String get() {
  684. return "A";
  685. }
  686. });
  687. }
  688. });
  689. assertEquals("A", bindInjector.getInstance(StringRemoteProvider.class).get());
  690. }
  691. public void testBindingToInterfaceWithBoundValueType_Provides() throws RemoteException {
  692. providesInjector = Guice.createInjector(new AbstractModule() {
  693. @Override
  694. protected void configure() {
  695. install(ThrowingProviderBinder.forModule(this));
  696. }
  697. @SuppressWarnings("unused")
  698. @CheckedProvides(StringRemoteProvider.class)
  699. String foo() throws RemoteException {
  700. return "A";
  701. }
  702. });
  703. assertEquals("A", providesInjector.getInstance(StringRemoteProvider.class).get());
  704. }
  705. interface StringRemoteProvider extends CheckedProvider<String> {
  706. @Override String get() throws RemoteException;
  707. }
  708. @SuppressWarnings("deprecation")
  709. public void testBindingToInterfaceWithGeneric_Bind() throws Exception {
  710. bindInjector = Guice.createInjector(new AbstractModule() {
  711. @Override
  712. protected void configure() {
  713. ThrowingProviderBinder.create(binder())
  714. .bind(RemoteProvider.class, new TypeLiteral<List<String>>() { }.getType())
  715. .to(new RemoteProvider<List<String>>() {
  716. public List<String> get() {
  717. return Arrays.asList("A", "B");
  718. }
  719. });
  720. }
  721. });
  722. Key<RemoteProvider<List<String>>> key
  723. = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
  724. assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
  725. }
  726. public void testBindingToInterfaceWithGeneric_BindUsingTypeLiteral() throws Exception {
  727. bindInjector = Guice.createInjector(new AbstractModule() {
  728. @Override
  729. protected void configure() {
  730. ThrowingProviderBinder.create(binder())
  731. .bind(RemoteProvider.class, new TypeLiteral<List<String>>() {})
  732. .to(new RemoteProvider<List<String>>() {
  733. public List<String> get() {
  734. return Arrays.asList("A", "B");
  735. }
  736. });
  737. }
  738. });
  739. Key<RemoteProvider<List<String>>> key
  740. = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
  741. assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
  742. }
  743. public void testBindingToInterfaceWithGeneric_Provides() throws Exception {
  744. providesInjector = Guice.createInjector(new AbstractModule() {
  745. @Override
  746. protected void configure() {
  747. install(ThrowingProviderBinder.forModule(this));
  748. }
  749. @SuppressWarnings("unused")
  750. @CheckedProvides(RemoteProvider.class)
  751. List<String> foo() throws RemoteException {
  752. return Arrays.asList("A", "B");
  753. }
  754. });
  755. Key<RemoteProvider<List<String>>> key
  756. = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
  757. assertEquals(Arrays.asList("A", "B"), providesInjector.getInstance(key).get());
  758. }
  759. public void testBindingToInterfaceWithGeneric_Cxtor() throws Exception {
  760. cxtorInjector = Guice.createInjector(new AbstractModule() {
  761. @Override
  762. protected void configure() {
  763. ThrowingProviderBinder.create(binder())
  764. .bind(RemoteProvider.class, new TypeLiteral<List<String>>() {})
  765. .providing(new TypeLiteral<ThrowingArrayList<String>>() {});
  766. }
  767. });
  768. Key<RemoteProvider<List<String>>> key
  769. = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
  770. assertEquals(Arrays.asList(), cxtorInjector.getInstance(key).get());
  771. }
  772. private static class ThrowingArrayList<T> extends ArrayList<T> {
  773. @SuppressWarnings("unused")
  774. @ThrowingInject
  775. ThrowingArrayList() {}
  776. }
  777. public void testProviderMethodWithWrongException() {
  778. try {
  779. Guice.createInjector(new AbstractModule() {
  780. @Override
  781. protected void configure() {
  782. install(ThrowingProviderBinder.forModule(this));
  783. }
  784. @SuppressWarnings("unused")
  785. @CheckedProvides(RemoteProvider.class)
  786. String foo() throws InterruptedException {
  787. return null;
  788. }
  789. });
  790. fail();
  791. } catch(CreationException ce) {
  792. assertEquals(InterruptedException.class.getName()
  793. + " is not compatible with the exceptions (["
  794. + RemoteException.class + ", " + BindException.class
  795. + "]) declared in the CheckedProvider interface ("
  796. + RemoteProvider.class.getName()
  797. + ")",
  798. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  799. }
  800. }
  801. public void testCxtorWithWrongException() {
  802. try {
  803. Guice.createInjector(new AbstractModule() {
  804. @Override
  805. protected void configure() {
  806. ThrowingProviderBinder.create(binder())
  807. .bind(RemoteProvider.class, Foo.class)
  808. .providing(WrongExceptionFoo.class);
  809. }
  810. });
  811. fail();
  812. } catch (CreationException ce) {
  813. assertEquals(InterruptedException.class.getName()
  814. + " is not compatible with the exceptions (["
  815. + RemoteException.class + ", " + BindException.class
  816. + "]) declared in the CheckedProvider interface ("
  817. + RemoteProvider.class.getName()
  818. + ")",
  819. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  820. }
  821. }
  822. static class WrongExceptionFoo implements Foo {
  823. @SuppressWarnings("unused")
  824. @ThrowingInject
  825. public WrongExceptionFoo() throws InterruptedException {
  826. }
  827. @Override
  828. public String s() { return null; }
  829. }
  830. public void testProviderMethodWithSubclassOfExceptionIsOk() throws Exception {
  831. providesInjector = Guice.createInjector(new AbstractModule() {
  832. @Override
  833. protected void configure() {
  834. install(ThrowingProviderBinder.forModule(this));
  835. }
  836. @SuppressWarnings("unused")
  837. @CheckedProvides(RemoteProvider.class)
  838. Foo foo() throws AccessException {
  839. throw new AccessException("boo!");
  840. }
  841. });
  842. RemoteProvider<Foo> remoteProvider =
  843. providesInjector.getInstance(Key.get(remoteProviderOfFoo));
  844. try {
  845. remoteProvider.get();
  846. fail();
  847. } catch (RemoteException expected) {
  848. assertTrue(expected instanceof AccessException);
  849. assertEquals("boo!", expected.getMessage());
  850. }
  851. }
  852. public void testCxtorWithSubclassOfExceptionIsOk() throws Exception {
  853. cxtorInjector = Guice.createInjector(new AbstractModule() {
  854. @Override
  855. protected void configure() {
  856. ThrowingProviderBinder.create(binder())
  857. .bind(RemoteProvider.class, Foo.class)
  858. .providing(SubclassExceptionFoo.class);
  859. }
  860. });
  861. RemoteProvider<Foo> remoteProvider =
  862. cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
  863. try {
  864. remoteProvider.get();
  865. fail();
  866. } catch (RemoteException expected) {
  867. assertTrue(expected instanceof AccessException);
  868. assertEquals("boo!", expected.getMessage());
  869. }
  870. }
  871. static class SubclassExceptionFoo implements Foo {
  872. @ThrowingInject
  873. public SubclassExceptionFoo() throws AccessException {
  874. throw new AccessException("boo!");
  875. }
  876. @Override
  877. public String s() { return null; }
  878. }
  879. public void testProviderMethodWithSuperclassExceptionFails() {
  880. try {
  881. Guice.createInjector(new AbstractModule() {
  882. @Override
  883. protected void configure() {
  884. install(ThrowingProviderBinder.forModule(this));
  885. }
  886. @SuppressWarnings("unused")
  887. @CheckedProvides(RemoteProvider.class)
  888. Foo foo() throws IOException {
  889. return null;
  890. }
  891. });
  892. fail();
  893. } catch(CreationException ce) {
  894. assertEquals(IOException.class.getName()
  895. + " is not compatible with the exceptions (["
  896. + RemoteException.class + ", " + BindException.class
  897. + "]) declared in the CheckedProvider interface ("
  898. + RemoteProvider.class.getName()
  899. + ")",
  900. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  901. }
  902. }
  903. public void testCxtorWithSuperclassExceptionFails() {
  904. try {
  905. Guice.createInjector(new AbstractModule() {
  906. @Override
  907. protected void configure() {
  908. ThrowingProviderBinder.create(binder())
  909. .bind(RemoteProvider.class, Foo.class)
  910. .providing(SuperclassExceptionFoo.class);
  911. }
  912. });
  913. fail();
  914. } catch (CreationException ce) {
  915. assertEquals(IOException.class.getName()
  916. + " is not compatible with the exceptions (["
  917. + RemoteException.class + ", " + BindException.class
  918. + "]) declared in the CheckedProvider interface ("
  919. + RemoteProvider.class.getName()
  920. + ")",
  921. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  922. }
  923. }
  924. static class SuperclassExceptionFoo implements Foo {
  925. @SuppressWarnings("unused")
  926. @ThrowingInject
  927. public SuperclassExceptionFoo() throws IOException {
  928. }
  929. @Override
  930. public String s() { return null; }
  931. }
  932. public void testProviderMethodWithRuntimeExceptionsIsOk() throws Exception {
  933. providesInjector = Guice.createInjector(new AbstractModule() {
  934. @Override
  935. protected void configure() {
  936. install(ThrowingProviderBinder.forModule(this));
  937. }
  938. @SuppressWarnings("unused")
  939. @CheckedProvides(RemoteProvider.class)
  940. Foo foo() throws RuntimeException {
  941. throw new RuntimeException("boo!");
  942. }
  943. });
  944. RemoteProvider<Foo> remoteProvider =
  945. providesInjector.getInstance(Key.get(remoteProviderOfFoo));
  946. try {
  947. remoteProvider.get();
  948. fail();
  949. } catch (RuntimeException expected) {
  950. assertEquals("boo!", expected.getCause().getMessage());
  951. }
  952. }
  953. public void testCxtorWithRuntimeExceptionsIsOk() throws Exception {
  954. cxtorInjector = Guice.createInjector(new AbstractModule() {
  955. @Override
  956. protected void configure() {
  957. ThrowingProviderBinder.create(binder())
  958. .bind(RemoteProvider.class, Foo.class)
  959. .providing(RuntimeExceptionFoo.class);
  960. }
  961. });
  962. RemoteProvider<Foo> remoteProvider =
  963. cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
  964. try {
  965. remoteProvider.get();
  966. fail();
  967. } catch (RuntimeException expected) {
  968. assertEquals("boo!", expected.getCause().getMessage());
  969. }
  970. }
  971. static class RuntimeExceptionFoo implements Foo {
  972. @ThrowingInject
  973. public RuntimeExceptionFoo() throws RuntimeException {
  974. throw new RuntimeException("boo!");
  975. }
  976. @Override
  977. public String s() { return null; }
  978. }
  979. private static class SubBindException extends BindException {}
  980. public void testProviderMethodWithManyExceptions() {
  981. try {
  982. Guice.createInjector(new AbstractModule() {
  983. @Override
  984. protected void configure() {
  985. install(ThrowingProviderBinder.forModule(this));
  986. }
  987. @SuppressWarnings("unused")
  988. @CheckedProvides(RemoteProvider.class)
  989. String foo() throws InterruptedException, RuntimeException, RemoteException,
  990. AccessException, TooManyListenersException,
  991. BindException, SubBindException {
  992. return null;
  993. }
  994. });
  995. fail();
  996. } catch(CreationException ce) {
  997. // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK.
  998. List<Message> errors = ImmutableList.copyOf(ce.getErrorMessages());
  999. assertEquals(InterruptedException.class.getName()
  1000. + " is not compatible with the exceptions (["
  1001. + RemoteException.class + ", " + BindException.class
  1002. + "]) declared in the CheckedProvider interface ("
  1003. + RemoteProvider.class.getName()
  1004. + ")",
  1005. errors.get(0).getMessage());
  1006. assertEquals(TooManyListenersException.class.getName()
  1007. + " is not compatible with the exceptions (["
  1008. + RemoteException.class + ", " + BindException.class
  1009. + "]) declared in the CheckedProvider interface ("
  1010. + RemoteProvider.class.getName()
  1011. + ")",
  1012. errors.get(1).getMessage());
  1013. assertEquals(2, errors.size());
  1014. }
  1015. }
  1016. public void testCxtorWithManyExceptions() {
  1017. try {
  1018. Guice.createInjector(new AbstractModule() {
  1019. @Override
  1020. protected void configure() {
  1021. ThrowingProviderBinder.create(binder())
  1022. .bind(RemoteProvider.class, Foo.class)
  1023. .providing(ManyExceptionFoo.class);
  1024. }
  1025. });
  1026. fail();
  1027. } catch (CreationException ce) {
  1028. // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK.
  1029. List<Message> errors = ImmutableList.copyOf(ce.getErrorMessages());
  1030. assertEquals(InterruptedException.class.getName()
  1031. + " is not compatible with the exceptions (["
  1032. + RemoteException.class + ", " + BindException.class
  1033. + "]) declared in the CheckedProvider interface ("
  1034. + RemoteProvider.class.getName()
  1035. + ")",
  1036. errors.get(0).getMessage());
  1037. assertEquals(TooManyListenersException.class.getName()
  1038. + " is not compatible with the exceptions (["
  1039. + RemoteException.class + ", " + BindException.class
  1040. + "]) declared in the CheckedProvider interface ("
  1041. + RemoteProvider.class.getName()
  1042. + ")",
  1043. errors.get(1).getMessage());
  1044. assertEquals(2, errors.size());
  1045. }
  1046. }
  1047. static class ManyExceptionFoo implements Foo {
  1048. @SuppressWarnings("unused")
  1049. @ThrowingInject
  1050. public ManyExceptionFoo()
  1051. throws InterruptedException,
  1052. RuntimeException,
  1053. RemoteException,
  1054. AccessException,
  1055. TooManyListenersException,
  1056. BindException,
  1057. SubBindException {
  1058. }
  1059. @Override
  1060. public String s() { return null; }
  1061. }
  1062. public void testMoreTypeParameters() {
  1063. try {
  1064. Guice.createInjector(new AbstractModule() {
  1065. @Override
  1066. protected void configure() {
  1067. install(ThrowingProviderBinder.forModule(this));
  1068. }
  1069. @SuppressWarnings("unused")
  1070. @CheckedProvides(TooManyTypeParameters.class)
  1071. String foo() {
  1072. return null;
  1073. }
  1074. });
  1075. fail();
  1076. } catch(CreationException ce) {
  1077. assertEquals(TooManyTypeParameters.class.getName() + " has more than one generic type parameter: [T, P]",
  1078. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  1079. }
  1080. }
  1081. public void testWrongThrowingProviderType() {
  1082. try {
  1083. Guice.createInjector(new AbstractModule() {
  1084. @Override
  1085. protected void configure() {
  1086. install(ThrowingProviderBinder.forModule(this));
  1087. }
  1088. @SuppressWarnings("unused")
  1089. @CheckedProvides(WrongThrowingProviderType.class)
  1090. String foo() {
  1091. return null;
  1092. }
  1093. });
  1094. fail();
  1095. } catch(CreationException ce) {
  1096. assertEquals(WrongThrowingProviderType.class.getName()
  1097. + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider "
  1098. + "(java.lang.String) is not a generic type",
  1099. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  1100. }
  1101. }
  1102. public void testOneMethodThatIsntGet() {
  1103. try {
  1104. Guice.createInjector(new AbstractModule() {
  1105. @Override
  1106. protected void configure() {
  1107. install(ThrowingProviderBinder.forModule(this));
  1108. }
  1109. @SuppressWarnings("unused")
  1110. @CheckedProvides(OneNoneGetMethod.class)
  1111. String foo() {
  1112. return null;
  1113. }
  1114. });
  1115. fail();
  1116. } catch(CreationException ce) {
  1117. assertEquals(OneNoneGetMethod.class.getName()
  1118. + " may not declare any new methods, but declared " + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]),
  1119. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  1120. }
  1121. }
  1122. public void testManyMethods() {
  1123. try {
  1124. Guice.createInjector(new AbstractModule() {
  1125. @Override
  1126. protected void configure() {
  1127. install(ThrowingProviderBinder.forModule(this));
  1128. }
  1129. @SuppressWarnings("unused")
  1130. @CheckedProvides(ManyMethods.class)
  1131. String foo() {
  1132. return null;
  1133. }
  1134. });
  1135. fail();
  1136. } catch(CreationException ce) {
  1137. assertEquals(ManyMethods.class.getName()
  1138. + " may not declare any new methods, but declared " + Arrays.asList(ManyMethods.class.getDeclaredMethods()),
  1139. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  1140. }
  1141. }
  1142. public void testIncorrectPredefinedType_Bind() {
  1143. try {
  1144. Guice.createInjector(new AbstractModule() {
  1145. @Override
  1146. protected void configure() {
  1147. ThrowingProviderBinder.create(binder())
  1148. .bind(StringRemoteProvider.class, Integer.class)
  1149. .to(new StringRemoteProvider() {
  1150. public String get() {
  1151. return "A";
  1152. }
  1153. });
  1154. }
  1155. });
  1156. fail();
  1157. } catch(CreationException ce) {
  1158. assertEquals(StringRemoteProvider.class.getName()
  1159. + " expects the value type to be java.lang.String, but it was java.lang.Integer",
  1160. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  1161. }
  1162. }
  1163. public void testIncorrectPredefinedType_Provides() {
  1164. try {
  1165. Guice.createInjector(new AbstractModule() {
  1166. @Override
  1167. protected void configure() {
  1168. install(ThrowingProviderBinder.forModule(this));
  1169. }
  1170. @SuppressWarnings("unused")
  1171. @CheckedProvides(StringRemoteProvider.class)
  1172. Integer foo() {
  1173. return null;
  1174. }
  1175. });
  1176. fail();
  1177. } catch(CreationException ce) {
  1178. assertEquals(StringRemoteProvider.class.getName()
  1179. + " expects the value type to be java.lang.String, but it was java.lang.Integer",
  1180. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  1181. }
  1182. }
  1183. private static interface TooManyTypeParameters<T, P> extends CheckedProvider<T> {
  1184. }
  1185. private static interface WrongThrowingProviderType<T> extends CheckedProvider<String> {
  1186. }
  1187. private static interface OneNoneGetMethod<T> extends CheckedProvider<T> {
  1188. T bar();
  1189. }
  1190. private static interface ManyMethods<T> extends CheckedProvider<T> {
  1191. T bar();
  1192. String baz();
  1193. }
  1194. public void testResultSerializes() throws Exception {
  1195. Result result = Result.forValue("foo");
  1196. result = Asserts.reserialize(result);
  1197. assertEquals("foo", result.getOrThrow());
  1198. }
  1199. public void testResultExceptionSerializes() throws Exception {
  1200. Result result = Result.forException(new Exception("boo"));
  1201. result = Asserts.reserialize(result);
  1202. try {
  1203. result.getOrThrow();
  1204. fail();
  1205. } catch(Exception ex) {
  1206. assertEquals("boo", ex.getMessage());
  1207. }
  1208. }
  1209. public void testEarlyBindingError() {
  1210. try {
  1211. Guice.createInjector(new AbstractModule() {
  1212. @Override
  1213. protected void configure() {
  1214. ThrowingProviderBinder.create(binder())
  1215. .bind(StringRemoteProvider.class, String.class)
  1216. .to(FailingProvider.class);
  1217. }
  1218. });
  1219. fail();
  1220. } catch(CreationException ce) {
  1221. assertEquals("Could not find a suitable constructor in " + FailingProvider.class.getName()
  1222. + ". Classes must have either one (and only one) constructor annotated with @Inject"
  1223. + " or a zero-argument constructor that is not private.",
  1224. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  1225. }
  1226. }
  1227. private static class FailingProvider implements StringRemoteProvider {
  1228. // no @Inject.
  1229. @SuppressWarnings("unused")
  1230. FailingProvider(Integer foo) {}
  1231. public String get() {
  1232. return null;
  1233. }
  1234. }
  1235. public void testNoInjectionPointForUsing() {
  1236. try {
  1237. Guice.createInjector(new AbstractModule() {
  1238. @Override
  1239. protected void configure() {
  1240. ThrowingProviderBinder.create(binder())
  1241. .bind(RemoteProvider.class, Foo.class)
  1242. .providing(InvalidFoo.class);
  1243. }
  1244. });
  1245. fail();
  1246. } catch (CreationException ce) {
  1247. assertEquals("Could not find a suitable constructor in " + InvalidFoo.class.getName()
  1248. + ". Classes must have either one (and only one) constructor annotated with "
  1249. + "@ThrowingInject.",
  1250. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  1251. }
  1252. }
  1253. static class InvalidFoo implements Foo {
  1254. public InvalidFoo(String dep) {
  1255. }
  1256. @Override public String s() { return null; }
  1257. }
  1258. public void testNoThrowingInject() {
  1259. try {
  1260. Guice.createInjector(new AbstractModule() {
  1261. @Override
  1262. protected void configure() {
  1263. ThrowingProviderBinder.create(binder())
  1264. .bind(RemoteProvider.class, Foo.class)
  1265. .providing(NormalInjectableFoo.class);
  1266. }
  1267. });
  1268. fail();
  1269. } catch (CreationException ce) {
  1270. assertEquals("Could not find a suitable constructor in " + NormalInjectableFoo.class.getName()
  1271. + ". Classes must have either one (and only one) constructor annotated with "
  1272. + "@ThrowingInject.",
  1273. Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
  1274. }
  1275. }
  1276. static class NormalInjectableFoo implements Foo {
  1277. @Inject
  1278. public NormalInjectableFoo() {
  1279. }
  1280. @Override public String s() { return null; }
  1281. }
  1282. public void testProvisionExceptionOnDependenciesOfCxtor() throws Exception {
  1283. Injector injector = Guice.createInjector(new AbstractModule() {
  1284. @Override
  1285. protected void configure() {
  1286. ThrowingProviderBinder.create(binder())
  1287. .bind(RemoteProvider.class, Foo.class)
  1288. .providing(ProvisionExceptionFoo.class);
  1289. bindScope(BadScope.class, new Scope() {
  1290. @Override
  1291. public <T> Provider<T> scope(final Key<T> key, Provider<T> unscoped) {
  1292. return new Provider<T>() {
  1293. @Override