blob: 1f4f97753cc2e4b6676533022d2e2b08fea441d2 [file] [log] [blame]
limpbizkite451ef72007-12-19 01:15:59 +00001/**
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
17package com.google.inject.throwingproviders;
18
cnesterfb04cae2015-03-02 10:11:36 -080019import static java.lang.annotation.ElementType.METHOD;
20import static java.lang.annotation.RetentionPolicy.RUNTIME;
21
sberlinb7a02b02011-07-08 00:34:16 +000022import com.google.common.base.Function;
23import com.google.common.collect.ImmutableList;
24import com.google.common.collect.ImmutableSet;
25import com.google.common.collect.Iterables;
Sam Berlin8b7aaec2012-05-27 13:42:13 -040026import com.google.common.collect.Lists;
limpbizkit49f67c02008-06-10 20:56:17 +000027import com.google.inject.AbstractModule;
sberlin488284d2010-11-17 14:27:41 +000028import com.google.inject.Asserts;
cnesterfb04cae2015-03-02 10:11:36 -080029import com.google.inject.BindingAnnotation;
limpbizkita6e0e782008-09-03 06:19:56 +000030import com.google.inject.CreationException;
limpbizkit49f67c02008-06-10 20:56:17 +000031import com.google.inject.Guice;
sberlin5ac45a82010-10-16 21:38:22 +000032import com.google.inject.Inject;
limpbizkit49f67c02008-06-10 20:56:17 +000033import com.google.inject.Injector;
34import com.google.inject.Key;
Sam Berlin8b7aaec2012-05-27 13:42:13 -040035import com.google.inject.OutOfScopeException;
36import com.google.inject.Provider;
37import com.google.inject.ProvisionException;
38import com.google.inject.Scope;
39import com.google.inject.ScopeAnnotation;
limpbizkit49f67c02008-06-10 20:56:17 +000040import com.google.inject.TypeLiteral;
sberlindfee9fd2010-10-30 14:15:06 +000041import com.google.inject.internal.util.Classes;
sberlinee446ca2010-10-24 21:36:39 +000042import com.google.inject.name.Named;
limpbizkite451ef72007-12-19 01:15:59 +000043import com.google.inject.name.Names;
sberlin5ac45a82010-10-16 21:38:22 +000044import com.google.inject.spi.Dependency;
45import com.google.inject.spi.HasDependencies;
sberlinee446ca2010-10-24 21:36:39 +000046import com.google.inject.spi.Message;
sberlin488284d2010-11-17 14:27:41 +000047import com.google.inject.throwingproviders.ThrowingProviderBinder.Result;
sberlin5ac45a82010-10-16 21:38:22 +000048
sberlinb7a02b02011-07-08 00:34:16 +000049import junit.framework.TestCase;
50
sberlinee446ca2010-10-24 21:36:39 +000051import java.io.IOException;
cnesterfb04cae2015-03-02 10:11:36 -080052import java.lang.annotation.Annotation;
Sam Berlin8b7aaec2012-05-27 13:42:13 -040053import java.lang.annotation.ElementType;
54import java.lang.annotation.Retention;
55import java.lang.annotation.RetentionPolicy;
56import java.lang.annotation.Target;
sberlin488284d2010-11-17 14:27:41 +000057import java.net.BindException;
sberlinee446ca2010-10-24 21:36:39 +000058import java.rmi.AccessException;
limpbizkite451ef72007-12-19 01:15:59 +000059import java.rmi.RemoteException;
Sam Berlin8557c772012-03-01 14:21:26 -050060import java.util.ArrayList;
limpbizkite451ef72007-12-19 01:15:59 +000061import java.util.Arrays;
62import java.util.List;
sberlin5ac45a82010-10-16 21:38:22 +000063import java.util.Set;
sberlinee446ca2010-10-24 21:36:39 +000064import java.util.TooManyListenersException;
sberlin5ac45a82010-10-16 21:38:22 +000065
limpbizkite451ef72007-12-19 01:15:59 +000066/**
67 * @author jmourits@google.com (Jerome Mourits)
68 * @author jessewilson@google.com (Jesse Wilson)
Sam Berlin8557c772012-03-01 14:21:26 -050069 * @author sameb@google.com (Sam Berlin)
limpbizkite451ef72007-12-19 01:15:59 +000070 */
sberlin488284d2010-11-17 14:27:41 +000071public class CheckedProviderTest extends TestCase {
cnesterfb04cae2015-03-02 10:11:36 -080072 @Target(METHOD) @Retention(RUNTIME) @BindingAnnotation
73 @interface NotExceptionScoping { };
Sam Berlin8557c772012-03-01 14:21:26 -050074
75 private static final Function<Dependency<?>, Key<?>> DEPENDENCY_TO_KEY =
76 new Function<Dependency<?>, Key<?>>() {
77 public Key<?> apply(Dependency<?> from) {
78 return from.getKey();
79 }
80 };
limpbizkite451ef72007-12-19 01:15:59 +000081
Sam Berlin8557c772012-03-01 14:21:26 -050082 private final TypeLiteral<RemoteProvider<Foo>> remoteProviderOfFoo
83 = new TypeLiteral<RemoteProvider<Foo>>() { };
84 private final MockRemoteProvider<Foo> mockRemoteProvider = new MockRemoteProvider<Foo>();
limpbizkite451ef72007-12-19 01:15:59 +000085 private final TestScope testScope = new TestScope();
Sam Berlin8557c772012-03-01 14:21:26 -050086
87 private Injector bindInjector;
88 private Injector providesInjector;
89 private Injector cxtorInjector;
90
91 @Override
92 protected void setUp() throws Exception {
93 MockFoo.nextToThrow = null;
94 MockFoo.nextToReturn = null;
95 AnotherMockFoo.nextToThrow = null;
96 AnotherMockFoo.nextToReturn = null;
sberlinee446ca2010-10-24 21:36:39 +000097
Sam Berlin8557c772012-03-01 14:21:26 -050098 bindInjector = Guice.createInjector(new AbstractModule() {
99 @Override
100 protected void configure() {
101 ThrowingProviderBinder.create(binder())
102 .bind(RemoteProvider.class, Foo.class)
103 .to(mockRemoteProvider)
104 .in(testScope);
cnesterfb04cae2015-03-02 10:11:36 -0800105
106 ThrowingProviderBinder.create(binder())
107 .bind(RemoteProvider.class, Foo.class)
108 .annotatedWith(NotExceptionScoping.class)
109 .scopeExceptions(false)
110 .to(mockRemoteProvider)
111 .in(testScope);
112
Sam Berlin8557c772012-03-01 14:21:26 -0500113 }
114 });
115
116 providesInjector = Guice.createInjector(new AbstractModule() {
117 @Override
118 protected void configure() {
119 install(ThrowingProviderBinder.forModule(this));
120 bindScope(TestScope.Scoped.class, testScope);
121 }
122
123 @SuppressWarnings("unused")
124 @CheckedProvides(RemoteProvider.class)
125 @TestScope.Scoped
126 Foo throwOrGet() throws RemoteException, BindException {
127 return mockRemoteProvider.get();
128 }
cnesterfb04cae2015-03-02 10:11:36 -0800129
130 @SuppressWarnings("unused")
131 @CheckedProvides(value = RemoteProvider.class, scopeExceptions = false)
132 @NotExceptionScoping
133 @TestScope.Scoped
134 Foo notExceptionScopingThrowOrGet() throws RemoteException, BindException {
135 return mockRemoteProvider.get();
136 }
137
Sam Berlin8557c772012-03-01 14:21:26 -0500138 });
139
140 cxtorInjector = Guice.createInjector(new AbstractModule() {
141 @Override
142 protected void configure() {
143 ThrowingProviderBinder.create(binder())
144 .bind(RemoteProvider.class, Foo.class)
145 .providing(MockFoo.class)
146 .in(testScope);
cnesterfb04cae2015-03-02 10:11:36 -0800147
148 ThrowingProviderBinder.create(binder())
149 .bind(RemoteProvider.class, Foo.class)
150 .annotatedWith(NotExceptionScoping.class)
151 .scopeExceptions(false)
152 .providing(MockFoo.class)
153 .in(testScope);
154
Sam Berlin8557c772012-03-01 14:21:26 -0500155 }
156 });
157 }
limpbizkite451ef72007-12-19 01:15:59 +0000158
sberlin488284d2010-11-17 14:27:41 +0000159 public void testExceptionsThrown_Bind() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000160 tExceptionsThrown(bindInjector);
161 }
162
sberlin488284d2010-11-17 14:27:41 +0000163 public void testExceptionsThrown_Provides() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000164 tExceptionsThrown(providesInjector);
165 }
166
Sam Berlin8557c772012-03-01 14:21:26 -0500167 public void testExceptionsThrown_Cxtor() throws Exception {
168 tExceptionsThrown(cxtorInjector);
169 }
170
sberlin488284d2010-11-17 14:27:41 +0000171 private void tExceptionsThrown(Injector injector) throws Exception {
Sam Berlin8557c772012-03-01 14:21:26 -0500172 RemoteProvider<Foo> remoteProvider =
173 injector.getInstance(Key.get(remoteProviderOfFoo));
limpbizkite451ef72007-12-19 01:15:59 +0000174
sberlin488284d2010-11-17 14:27:41 +0000175 mockRemoteProvider.throwOnNextGet(new BindException("kaboom!"));
Sam Berlin8557c772012-03-01 14:21:26 -0500176 MockFoo.nextToThrow = new BindException("kaboom!");
limpbizkite451ef72007-12-19 01:15:59 +0000177 try {
178 remoteProvider.get();
179 fail();
sberlin488284d2010-11-17 14:27:41 +0000180 } catch (BindException expected) {
limpbizkite451ef72007-12-19 01:15:59 +0000181 assertEquals("kaboom!", expected.getMessage());
182 }
183 }
184
sberlin488284d2010-11-17 14:27:41 +0000185 public void testValuesScoped_Bind() throws Exception {
cnesterfb04cae2015-03-02 10:11:36 -0800186 tValuesScoped(bindInjector, null);
sberlinee446ca2010-10-24 21:36:39 +0000187 }
188
sberlin488284d2010-11-17 14:27:41 +0000189 public void testValuesScoped_Provides() throws Exception {
cnesterfb04cae2015-03-02 10:11:36 -0800190 tValuesScoped(providesInjector, null);
sberlinee446ca2010-10-24 21:36:39 +0000191 }
192
cnesterfb04cae2015-03-02 10:11:36 -0800193 public void testValuesScopedWhenNotExceptionScoping_Bind() throws Exception {
194 tValuesScoped(bindInjector, NotExceptionScoping.class);
195 }
196
197 public void testValuesScopedWhenNotExceptionScoping_Provides() throws Exception {
198 tValuesScoped(providesInjector, NotExceptionScoping.class);
199 }
limpbizkite451ef72007-12-19 01:15:59 +0000200
cnesterfb04cae2015-03-02 10:11:36 -0800201 private void tValuesScoped(Injector injector,
202 Class<? extends Annotation> annotation) throws Exception {
203 Key<RemoteProvider<Foo>> key = annotation != null ?
204 Key.get(remoteProviderOfFoo, annotation) :
205 Key.get(remoteProviderOfFoo);
206 RemoteProvider<Foo> remoteProvider = injector.getInstance(key);
207
Sam Berlin8557c772012-03-01 14:21:26 -0500208 mockRemoteProvider.setNextToReturn(new SimpleFoo("A"));
209 assertEquals("A", remoteProvider.get().s());
limpbizkite451ef72007-12-19 01:15:59 +0000210
Sam Berlin8557c772012-03-01 14:21:26 -0500211 mockRemoteProvider.setNextToReturn(new SimpleFoo("B"));
212 assertEquals("A", remoteProvider.get().s());
limpbizkite451ef72007-12-19 01:15:59 +0000213
214 testScope.beginNewScope();
Sam Berlin8557c772012-03-01 14:21:26 -0500215 assertEquals("B", remoteProvider.get().s());
216 }
217
218 public void testValuesScoped_Cxtor() throws Exception {
219 RemoteProvider<Foo> remoteProvider =
220 cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
221
222 Foo retrieved = remoteProvider.get();
223 assertSame(retrieved, remoteProvider.get()); // same, not in new scope.
224
225 testScope.beginNewScope();
226 assertNotSame(retrieved, remoteProvider.get()); // different, new scope.
limpbizkite451ef72007-12-19 01:15:59 +0000227 }
228
sberlin488284d2010-11-17 14:27:41 +0000229 public void testExceptionsScoped_Bind() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000230 tExceptionsScoped(bindInjector);
231 }
232
sberlin488284d2010-11-17 14:27:41 +0000233 public void testExceptionsScoped_Provides() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000234 tExceptionsScoped(providesInjector);
235 }
236
Sam Berlin8557c772012-03-01 14:21:26 -0500237 public void testExceptionScopes_Cxtor() throws Exception {
238 tExceptionsScoped(cxtorInjector);
239 }
240
sberlin488284d2010-11-17 14:27:41 +0000241 private void tExceptionsScoped(Injector injector) throws Exception {
Sam Berlin8557c772012-03-01 14:21:26 -0500242 RemoteProvider<Foo> remoteProvider =
243 injector.getInstance(Key.get(remoteProviderOfFoo));
limpbizkite451ef72007-12-19 01:15:59 +0000244
sberlin488284d2010-11-17 14:27:41 +0000245 mockRemoteProvider.throwOnNextGet(new RemoteException("A"));
Sam Berlin8557c772012-03-01 14:21:26 -0500246 MockFoo.nextToThrow = new RemoteException("A");
limpbizkite451ef72007-12-19 01:15:59 +0000247 try {
248 remoteProvider.get();
249 fail();
250 } catch (RemoteException expected) {
251 assertEquals("A", expected.getMessage());
252 }
253
sberlin488284d2010-11-17 14:27:41 +0000254 mockRemoteProvider.throwOnNextGet(new RemoteException("B"));
Sam Berlin8557c772012-03-01 14:21:26 -0500255 MockFoo.nextToThrow = new RemoteException("B");
limpbizkite451ef72007-12-19 01:15:59 +0000256 try {
257 remoteProvider.get();
258 fail();
259 } catch (RemoteException expected) {
260 assertEquals("A", expected.getMessage());
261 }
262 }
263
cnesterfb04cae2015-03-02 10:11:36 -0800264 public void testExceptionsNotScopedWhenNotExceptionScoping_Bind() throws Exception {
265 tExceptionsNotScopedWhenNotExceptionScoping(bindInjector);
266 }
267
268 public void testExceptionsNotScopedWhenNotExceptionScoping_Provides() throws Exception {
269 tExceptionsNotScopedWhenNotExceptionScoping(providesInjector);
270 }
271
272 public void testExceptionNotScopedWhenNotExceptionScoping_Cxtor() throws Exception {
273 tExceptionsNotScopedWhenNotExceptionScoping(cxtorInjector);
274 }
275
276 private void tExceptionsNotScopedWhenNotExceptionScoping(Injector injector) throws Exception {
277 RemoteProvider<Foo> remoteProvider =
278 injector.getInstance(Key.get(remoteProviderOfFoo, NotExceptionScoping.class));
279
280 mockRemoteProvider.throwOnNextGet(new RemoteException("A"));
281 MockFoo.nextToThrow = new RemoteException("A");
282 try {
283 remoteProvider.get();
284 fail();
285 } catch (RemoteException expected) {
286 assertEquals("A", expected.getMessage());
287 }
288
289 mockRemoteProvider.throwOnNextGet(new RemoteException("B"));
290 MockFoo.nextToThrow = new RemoteException("B");
291 try {
292 remoteProvider.get();
293 fail();
294 } catch (RemoteException expected) {
295 assertEquals("B", expected.getMessage());
296 }
297 }
298
sberlin488284d2010-11-17 14:27:41 +0000299 public void testAnnotations_Bind() throws Exception {
Sam Berlin8557c772012-03-01 14:21:26 -0500300 final MockRemoteProvider<Foo> mockRemoteProviderA = new MockRemoteProvider<Foo>();
301 final MockRemoteProvider<Foo> mockRemoteProviderB = new MockRemoteProvider<Foo>();
sberlinee446ca2010-10-24 21:36:39 +0000302 bindInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500303 @Override
limpbizkite451ef72007-12-19 01:15:59 +0000304 protected void configure() {
305 ThrowingProviderBinder.create(binder())
Sam Berlin8557c772012-03-01 14:21:26 -0500306 .bind(RemoteProvider.class, Foo.class)
limpbizkite451ef72007-12-19 01:15:59 +0000307 .annotatedWith(Names.named("a"))
308 .to(mockRemoteProviderA);
309
310 ThrowingProviderBinder.create(binder())
Sam Berlin8557c772012-03-01 14:21:26 -0500311 .bind(RemoteProvider.class, Foo.class)
limpbizkite451ef72007-12-19 01:15:59 +0000312 .to(mockRemoteProviderB);
313 }
314 });
sberlinee446ca2010-10-24 21:36:39 +0000315 tAnnotations(bindInjector, mockRemoteProviderA, mockRemoteProviderB);
316 }
317
sberlin488284d2010-11-17 14:27:41 +0000318 public void testAnnotations_Provides() throws Exception {
Sam Berlin8557c772012-03-01 14:21:26 -0500319 final MockRemoteProvider<Foo> mockRemoteProviderA = new MockRemoteProvider<Foo>();
320 final MockRemoteProvider<Foo> mockRemoteProviderB = new MockRemoteProvider<Foo>();
sberlinee446ca2010-10-24 21:36:39 +0000321 providesInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500322 @Override
sberlinee446ca2010-10-24 21:36:39 +0000323 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +0000324 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +0000325 }
326
327 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +0000328 @CheckedProvides(RemoteProvider.class)
sberlinee446ca2010-10-24 21:36:39 +0000329 @Named("a")
Sam Berlin8557c772012-03-01 14:21:26 -0500330 Foo throwOrGet() throws RemoteException, BindException {
sberlinee446ca2010-10-24 21:36:39 +0000331 return mockRemoteProviderA.get();
332 }
333
334 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +0000335 @CheckedProvides(RemoteProvider.class)
Sam Berlin8557c772012-03-01 14:21:26 -0500336 Foo throwOrGet2() throws RemoteException, BindException {
sberlinee446ca2010-10-24 21:36:39 +0000337 return mockRemoteProviderB.get();
338 }
339 });
340 tAnnotations(providesInjector, mockRemoteProviderA, mockRemoteProviderB);
341 }
342
Sam Berlin8557c772012-03-01 14:21:26 -0500343 private void tAnnotations(Injector injector, MockRemoteProvider<Foo> mockA,
344 MockRemoteProvider<Foo> mockB) throws Exception {
345 mockA.setNextToReturn(new SimpleFoo("A"));
346 mockB.setNextToReturn(new SimpleFoo("B"));
limpbizkite451ef72007-12-19 01:15:59 +0000347 assertEquals("A",
Sam Berlin8557c772012-03-01 14:21:26 -0500348 injector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s());
limpbizkite451ef72007-12-19 01:15:59 +0000349
350 assertEquals("B",
Sam Berlin8557c772012-03-01 14:21:26 -0500351 injector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
352 }
353
354 public void testAnnotations_Cxtor() throws Exception {
355 cxtorInjector = Guice.createInjector(new AbstractModule() {
356 @Override
357 protected void configure() {
358 ThrowingProviderBinder.create(binder())
359 .bind(RemoteProvider.class, Foo.class)
360 .annotatedWith(Names.named("a"))
361 .providing(MockFoo.class);
362
363 ThrowingProviderBinder.create(binder())
364 .bind(RemoteProvider.class, Foo.class)
365 .providing(AnotherMockFoo.class);
366 }
367 });
368 MockFoo.nextToReturn = "A";
369 AnotherMockFoo.nextToReturn = "B";
370 assertEquals("A",
371 cxtorInjector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s());
372
373 assertEquals("B",
374 cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
limpbizkite451ef72007-12-19 01:15:59 +0000375 }
376
sberlin488284d2010-11-17 14:27:41 +0000377 public void testUndeclaredExceptions_Bind() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000378 tUndeclaredExceptions(bindInjector);
379 }
380
sberlin488284d2010-11-17 14:27:41 +0000381 public void testUndeclaredExceptions_Provides() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000382 tUndeclaredExceptions(providesInjector);
383 }
Sam Berlin8557c772012-03-01 14:21:26 -0500384
385 public void testUndeclaredExceptions_Cxtor() throws Exception {
386 tUndeclaredExceptions(cxtorInjector);
387 }
sberlinee446ca2010-10-24 21:36:39 +0000388
sberlin488284d2010-11-17 14:27:41 +0000389 private void tUndeclaredExceptions(Injector injector) throws Exception {
Sam Berlin8557c772012-03-01 14:21:26 -0500390 RemoteProvider<Foo> remoteProvider =
391 injector.getInstance(Key.get(remoteProviderOfFoo));
limpbizkite451ef72007-12-19 01:15:59 +0000392 mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("A"));
Sam Berlin8557c772012-03-01 14:21:26 -0500393 MockFoo.nextToThrow = new IndexOutOfBoundsException("A");
limpbizkite451ef72007-12-19 01:15:59 +0000394 try {
395 remoteProvider.get();
396 fail();
397 } catch (RuntimeException e) {
limpbizkit49f67c02008-06-10 20:56:17 +0000398 assertEquals("A", e.getCause().getMessage());
limpbizkite451ef72007-12-19 01:15:59 +0000399 }
400
401 // undeclared exceptions shouldn't be scoped
402 mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("B"));
Sam Berlin8557c772012-03-01 14:21:26 -0500403 MockFoo.nextToThrow = new IndexOutOfBoundsException("B");
limpbizkite451ef72007-12-19 01:15:59 +0000404 try {
405 remoteProvider.get();
406 fail();
407 } catch (RuntimeException e) {
limpbizkit49f67c02008-06-10 20:56:17 +0000408 assertEquals("B", e.getCause().getMessage());
limpbizkite451ef72007-12-19 01:15:59 +0000409 }
410 }
411
sberlin488284d2010-11-17 14:27:41 +0000412 public void testThrowingProviderSubclassing() throws Exception {
limpbizkite451ef72007-12-19 01:15:59 +0000413 final SubMockRemoteProvider aProvider = new SubMockRemoteProvider();
Sam Berlin8557c772012-03-01 14:21:26 -0500414 aProvider.setNextToReturn(new SimpleFoo("A"));
limpbizkite451ef72007-12-19 01:15:59 +0000415
sberlinee446ca2010-10-24 21:36:39 +0000416 bindInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500417 @Override
limpbizkite451ef72007-12-19 01:15:59 +0000418 protected void configure() {
419 ThrowingProviderBinder.create(binder())
Sam Berlin8557c772012-03-01 14:21:26 -0500420 .bind(RemoteProvider.class, Foo.class)
limpbizkite451ef72007-12-19 01:15:59 +0000421 .to(aProvider);
422 }
423 });
424
425 assertEquals("A",
Sam Berlin8557c772012-03-01 14:21:26 -0500426 bindInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
limpbizkite451ef72007-12-19 01:15:59 +0000427 }
428
Sam Berlin8557c772012-03-01 14:21:26 -0500429 static class SubMockRemoteProvider extends MockRemoteProvider<Foo> { }
limpbizkite451ef72007-12-19 01:15:59 +0000430
sberlin488284d2010-11-17 14:27:41 +0000431 public void testBindingToNonInterfaceType_Bind() throws Exception {
limpbizkite451ef72007-12-19 01:15:59 +0000432 try {
sberlinee446ca2010-10-24 21:36:39 +0000433 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500434 @Override
limpbizkite451ef72007-12-19 01:15:59 +0000435 protected void configure() {
436 ThrowingProviderBinder.create(binder())
Sam Berlin8557c772012-03-01 14:21:26 -0500437 .bind(MockRemoteProvider.class, Foo.class)
limpbizkite451ef72007-12-19 01:15:59 +0000438 .to(mockRemoteProvider);
439 }
440 });
limpbizkiteab76472008-05-26 19:45:12 +0000441 fail();
limpbizkita6e0e782008-09-03 06:19:56 +0000442 } catch (CreationException expected) {
sberlinee446ca2010-10-24 21:36:39 +0000443 assertEquals(MockRemoteProvider.class.getName() + " must be an interface",
444 Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
limpbizkite451ef72007-12-19 01:15:59 +0000445 }
446 }
447
sberlin488284d2010-11-17 14:27:41 +0000448 public void testBindingToNonInterfaceType_Provides() throws Exception {
limpbizkite451ef72007-12-19 01:15:59 +0000449 try {
sberlinee446ca2010-10-24 21:36:39 +0000450 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500451 @Override
sberlinee446ca2010-10-24 21:36:39 +0000452 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +0000453 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +0000454 }
455
456 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +0000457 @CheckedProvides(MockRemoteProvider.class)
Sam Berlin8557c772012-03-01 14:21:26 -0500458 Foo foo() {
sberlinee446ca2010-10-24 21:36:39 +0000459 return null;
460 }
461 });
462 fail();
463 } catch (CreationException expected) {
464 assertEquals(MockRemoteProvider.class.getName() + " must be an interface",
465 Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
466 }
467 }
468
sberlin488284d2010-11-17 14:27:41 +0000469 public void testBindingToSubSubInterface_Bind() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000470 try {
471 bindInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500472 @Override
limpbizkite451ef72007-12-19 01:15:59 +0000473 protected void configure() {
474 ThrowingProviderBinder.create(binder())
Sam Berlin8557c772012-03-01 14:21:26 -0500475 .bind(SubRemoteProvider.class, Foo.class);
limpbizkite451ef72007-12-19 01:15:59 +0000476 }
477 });
limpbizkiteab76472008-05-26 19:45:12 +0000478 fail();
limpbizkita6e0e782008-09-03 06:19:56 +0000479 } catch (CreationException expected) {
sberlin488284d2010-11-17 14:27:41 +0000480 assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)",
sberlinee446ca2010-10-24 21:36:39 +0000481 Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
limpbizkite451ef72007-12-19 01:15:59 +0000482 }
483 }
sberlinee446ca2010-10-24 21:36:39 +0000484
sberlin488284d2010-11-17 14:27:41 +0000485 public void testBindingToSubSubInterface_Provides() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000486 try {
487 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500488 @Override
sberlinee446ca2010-10-24 21:36:39 +0000489 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +0000490 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +0000491 }
492
493 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +0000494 @CheckedProvides(SubRemoteProvider.class)
Sam Berlin8557c772012-03-01 14:21:26 -0500495 Foo foo() {
sberlinee446ca2010-10-24 21:36:39 +0000496 return null;
497 }
498 });
499 fail();
500 } catch (CreationException expected) {
sberlin488284d2010-11-17 14:27:41 +0000501 assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)",
sberlinee446ca2010-10-24 21:36:39 +0000502 Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
503 }
504 }
limpbizkite451ef72007-12-19 01:15:59 +0000505
506 interface SubRemoteProvider extends RemoteProvider<String> { }
507
sberlin488284d2010-11-17 14:27:41 +0000508 public void testBindingToInterfaceWithExtraMethod_Bind() throws Exception {
limpbizkite451ef72007-12-19 01:15:59 +0000509 try {
sberlinee446ca2010-10-24 21:36:39 +0000510 bindInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500511 @Override
limpbizkite451ef72007-12-19 01:15:59 +0000512 protected void configure() {
513 ThrowingProviderBinder.create(binder())
Sam Berlin8557c772012-03-01 14:21:26 -0500514 .bind(RemoteProviderWithExtraMethod.class, Foo.class);
limpbizkite451ef72007-12-19 01:15:59 +0000515 }
516 });
limpbizkiteab76472008-05-26 19:45:12 +0000517 fail();
limpbizkita6e0e782008-09-03 06:19:56 +0000518 } catch (CreationException expected) {
sberlinee446ca2010-10-24 21:36:39 +0000519 assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared "
520 + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(),
521 Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
limpbizkite451ef72007-12-19 01:15:59 +0000522 }
523 }
sberlin5ac45a82010-10-16 21:38:22 +0000524
sberlin488284d2010-11-17 14:27:41 +0000525 public void testBindingToInterfaceWithExtraMethod_Provides() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000526 try {
527 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500528 @Override
sberlinee446ca2010-10-24 21:36:39 +0000529 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +0000530 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +0000531 }
532
533 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +0000534 @CheckedProvides(RemoteProviderWithExtraMethod.class)
Sam Berlin8557c772012-03-01 14:21:26 -0500535 Foo foo() {
sberlinee446ca2010-10-24 21:36:39 +0000536 return null;
537 }
538 });
539 fail();
540 } catch (CreationException expected) {
541 assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared "
542 + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(),
543 Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
544 }
545 }
546
547 public void testDependencies_Bind() {
548 bindInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500549 @Override
sberlin5ac45a82010-10-16 21:38:22 +0000550 protected void configure() {
551 bind(String.class).toInstance("Foo");
552 bind(Integer.class).toInstance(5);
553 bind(Double.class).toInstance(5d);
554 bind(Long.class).toInstance(5L);
555 ThrowingProviderBinder.create(binder())
Sam Berlin8557c772012-03-01 14:21:26 -0500556 .bind(RemoteProvider.class, Foo.class)
sberlin5ac45a82010-10-16 21:38:22 +0000557 .to(DependentRemoteProvider.class);
558 }
559 });
560
561 HasDependencies hasDependencies =
Sam Berlin8557c772012-03-01 14:21:26 -0500562 (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfFoo));
sberlin5ac45a82010-10-16 21:38:22 +0000563 hasDependencies =
sberlinee446ca2010-10-24 21:36:39 +0000564 (HasDependencies)bindInjector.getBinding(
sberlin5ac45a82010-10-16 21:38:22 +0000565 Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
566 // Make sure that that is dependent on DependentRemoteProvider.
567 assertEquals(Dependency.get(Key.get(DependentRemoteProvider.class)),
568 Iterables.getOnlyElement(hasDependencies.getDependencies()));
569 // And make sure DependentRemoteProvider has the proper dependencies.
sberlinee446ca2010-10-24 21:36:39 +0000570 hasDependencies = (HasDependencies)bindInjector.getBinding(DependentRemoteProvider.class);
sberlin5ac45a82010-10-16 21:38:22 +0000571 Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
Sam Berlin8557c772012-03-01 14:21:26 -0500572 Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
sberlin5ac45a82010-10-16 21:38:22 +0000573 assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
574 Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
575 }
sberlinee446ca2010-10-24 21:36:39 +0000576
577 public void testDependencies_Provides() {
578 providesInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500579 @Override
sberlinee446ca2010-10-24 21:36:39 +0000580 protected void configure() {
581 bind(String.class).toInstance("Foo");
582 bind(Integer.class).toInstance(5);
583 bind(Double.class).toInstance(5d);
584 bind(Long.class).toInstance(5L);
sberlin488284d2010-11-17 14:27:41 +0000585 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +0000586 }
587
588 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +0000589 @CheckedProvides(RemoteProvider.class)
Sam Berlin8557c772012-03-01 14:21:26 -0500590 Foo foo(String s, Integer i, Double d, Long l) {
sberlinee446ca2010-10-24 21:36:39 +0000591 return null;
592 }
593 });
594
595 HasDependencies hasDependencies =
Sam Berlin8557c772012-03-01 14:21:26 -0500596 (HasDependencies) providesInjector.getBinding(Key.get(remoteProviderOfFoo));
sberlinee446ca2010-10-24 21:36:39 +0000597 // RemoteProvider<String> is dependent on the provider method..
Sam Berlin8557c772012-03-01 14:21:26 -0500598 hasDependencies = (HasDependencies) providesInjector.getBinding(
599 Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
sberlinee446ca2010-10-24 21:36:39 +0000600 // And the provider method has our real dependencies..
601 hasDependencies = (HasDependencies)providesInjector.getBinding(
602 Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
603 Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
Sam Berlin8557c772012-03-01 14:21:26 -0500604 Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
605 assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
606 Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
607 }
608
609 public void testDependencies_Cxtor() {
610 cxtorInjector = Guice.createInjector(new AbstractModule() {
611 @Override
612 protected void configure() {
613 bind(String.class).toInstance("Foo");
614 bind(Integer.class).toInstance(5);
615 bind(Double.class).toInstance(5d);
616 bind(Long.class).toInstance(5L);
617 ThrowingProviderBinder.create(binder())
618 .bind(RemoteProvider.class, Foo.class)
619 .providing(DependentMockFoo.class);
620 }
621 });
622
623 Key<?> key = Key.get(remoteProviderOfFoo);
624
625 // RemoteProvider<String> is dependent on Result.
626 HasDependencies hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
627 key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
628 assertEquals(Result.class, key.getTypeLiteral().getRawType());
629
630 // Result is dependent on the fake CheckedProvider impl
631 hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
632 key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
633 assertTrue(CheckedProvider.class.isAssignableFrom(key.getTypeLiteral().getRawType()));
634
635 // And the CheckedProvider is dependent on DependentMockFoo...
636 hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
637 key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
638 assertEquals(DependentMockFoo.class, key.getTypeLiteral().getRawType());
639
640 // And DependentMockFoo is dependent on the goods.
641 hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
642 Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
643 Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
sberlinee446ca2010-10-24 21:36:39 +0000644 assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
645 Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
646 }
limpbizkite451ef72007-12-19 01:15:59 +0000647
sberlin488284d2010-11-17 14:27:41 +0000648 interface RemoteProviderWithExtraMethod<T> extends CheckedProvider<T> {
649 T get(T defaultValue) throws RemoteException, BindException;
limpbizkite451ef72007-12-19 01:15:59 +0000650 }
651
sberlin488284d2010-11-17 14:27:41 +0000652 interface RemoteProvider<T> extends CheckedProvider<T> {
653 public T get() throws RemoteException, BindException;
654 }
limpbizkite451ef72007-12-19 01:15:59 +0000655
Sam Berlin8557c772012-03-01 14:21:26 -0500656 static class DependentMockFoo implements Foo {
657 @Inject double foo;
658
Sam Berline6abeff2012-05-27 13:39:59 -0400659 @ThrowingInject public DependentMockFoo(String foo, int bar) {
Sam Berlin8557c772012-03-01 14:21:26 -0500660 }
661
662 @Inject void initialize(long foo) {}
663
664 @Override
665 public String s() {
666 return null;
667 }
668 }
669
sberlin5ac45a82010-10-16 21:38:22 +0000670 static class DependentRemoteProvider<T> implements RemoteProvider<T> {
671 @Inject double foo;
672
673 @Inject public DependentRemoteProvider(String foo, int bar) {
674 }
675
676 @Inject void initialize(long foo) {}
677
Sam Berlin8557c772012-03-01 14:21:26 -0500678 public T get() {
sberlin5ac45a82010-10-16 21:38:22 +0000679 return null;
680 }
681 }
682
Sam Berlin8557c772012-03-01 14:21:26 -0500683 interface Foo {
684 String s();
685 }
686
687 static class SimpleFoo implements Foo {
688 private String s;
689
690 SimpleFoo(String s) {
691 this.s = s;
692 }
693
694 @Override
695 public String s() {
696 return s;
697 }
698
699 @Override
700 public String toString() {
701 return s;
702 }
703 }
704
705 static class MockFoo implements Foo {
706 static Exception nextToThrow;
707 static String nextToReturn;
708
Sam Berline6abeff2012-05-27 13:39:59 -0400709 @ThrowingInject
Sam Berlin8557c772012-03-01 14:21:26 -0500710 MockFoo() throws RemoteException, BindException {
711 if (nextToThrow instanceof RemoteException) {
712 throw (RemoteException) nextToThrow;
713 } else if (nextToThrow instanceof BindException) {
714 throw (BindException) nextToThrow;
715 } else if (nextToThrow instanceof RuntimeException) {
716 throw (RuntimeException) nextToThrow;
717 } else if (nextToThrow == null) {
718 // Do nothing, return this.
719 } else {
720 throw new AssertionError("nextToThrow must be a runtime or remote exception");
721 }
722 }
723
724 @Override
725 public String s() {
726 return nextToReturn;
727 }
728
729 @Override
730 public String toString() {
731 return nextToReturn;
732 }
733 }
734
735 static class AnotherMockFoo implements Foo {
736 static Exception nextToThrow;
737 static String nextToReturn;
738
Sam Berline6abeff2012-05-27 13:39:59 -0400739 @ThrowingInject
Sam Berlin8557c772012-03-01 14:21:26 -0500740 AnotherMockFoo() throws RemoteException, BindException {
741 if (nextToThrow instanceof RemoteException) {
742 throw (RemoteException) nextToThrow;
743 } else if (nextToThrow instanceof BindException) {
744 throw (BindException) nextToThrow;
745 } else if (nextToThrow instanceof RuntimeException) {
746 throw (RuntimeException) nextToThrow;
747 } else if (nextToThrow == null) {
748 // Do nothing, return this.
749 } else {
750 throw new AssertionError("nextToThrow must be a runtime or remote exception");
751 }
752 }
753
754 @Override
755 public String s() {
756 return nextToReturn;
757 }
758
759 @Override
760 public String toString() {
761 return nextToReturn;
762 }
763 }
764
limpbizkite451ef72007-12-19 01:15:59 +0000765 static class MockRemoteProvider<T> implements RemoteProvider<T> {
766 Exception nextToThrow;
767 T nextToReturn;
limpbizkite451ef72007-12-19 01:15:59 +0000768
769 public void throwOnNextGet(Exception nextToThrow) {
770 this.nextToThrow = nextToThrow;
771 }
772
773 public void setNextToReturn(T nextToReturn) {
774 this.nextToReturn = nextToReturn;
775 }
776
sberlin488284d2010-11-17 14:27:41 +0000777 public T get() throws RemoteException, BindException {
limpbizkite451ef72007-12-19 01:15:59 +0000778 if (nextToThrow instanceof RemoteException) {
779 throw (RemoteException) nextToThrow;
sberlin488284d2010-11-17 14:27:41 +0000780 } else if (nextToThrow instanceof BindException) {
781 throw (BindException) nextToThrow;
limpbizkite451ef72007-12-19 01:15:59 +0000782 } else if (nextToThrow instanceof RuntimeException) {
783 throw (RuntimeException) nextToThrow;
784 } else if (nextToThrow == null) {
785 return nextToReturn;
786 } else {
787 throw new AssertionError("nextToThrow must be a runtime or remote exception");
788 }
789 }
790 }
791
sberlinee446ca2010-10-24 21:36:39 +0000792 public void testBindingToInterfaceWithBoundValueType_Bind() throws RemoteException {
793 bindInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500794 @Override
limpbizkite451ef72007-12-19 01:15:59 +0000795 protected void configure() {
796 ThrowingProviderBinder.create(binder())
797 .bind(StringRemoteProvider.class, String.class)
798 .to(new StringRemoteProvider() {
Sam Berlin8557c772012-03-01 14:21:26 -0500799 public String get() {
limpbizkite451ef72007-12-19 01:15:59 +0000800 return "A";
801 }
802 });
803 }
804 });
805
sberlinee446ca2010-10-24 21:36:39 +0000806 assertEquals("A", bindInjector.getInstance(StringRemoteProvider.class).get());
807 }
808
809 public void testBindingToInterfaceWithBoundValueType_Provides() throws RemoteException {
810 providesInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500811 @Override
sberlinee446ca2010-10-24 21:36:39 +0000812 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +0000813 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +0000814 }
815
816 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +0000817 @CheckedProvides(StringRemoteProvider.class)
sberlinee446ca2010-10-24 21:36:39 +0000818 String foo() throws RemoteException {
819 return "A";
820 }
821 });
822
823 assertEquals("A", providesInjector.getInstance(StringRemoteProvider.class).get());
limpbizkite451ef72007-12-19 01:15:59 +0000824 }
825
sberlin488284d2010-11-17 14:27:41 +0000826 interface StringRemoteProvider extends CheckedProvider<String> {
Sam Berlinf9a3d2d2014-05-03 00:43:39 -0400827 @Override String get() throws RemoteException;
sberlin488284d2010-11-17 14:27:41 +0000828 }
limpbizkite451ef72007-12-19 01:15:59 +0000829
Sam Berlin8557c772012-03-01 14:21:26 -0500830 @SuppressWarnings("deprecation")
sberlin488284d2010-11-17 14:27:41 +0000831 public void testBindingToInterfaceWithGeneric_Bind() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000832 bindInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500833 @Override
limpbizkite451ef72007-12-19 01:15:59 +0000834 protected void configure() {
835 ThrowingProviderBinder.create(binder())
836 .bind(RemoteProvider.class, new TypeLiteral<List<String>>() { }.getType())
837 .to(new RemoteProvider<List<String>>() {
Sam Berlin8557c772012-03-01 14:21:26 -0500838 public List<String> get() {
839 return Arrays.asList("A", "B");
840 }
841 });
842 }
843 });
844
845 Key<RemoteProvider<List<String>>> key
846 = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
847 assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
848 }
849
850 public void testBindingToInterfaceWithGeneric_BindUsingTypeLiteral() throws Exception {
851 bindInjector = Guice.createInjector(new AbstractModule() {
852 @Override
853 protected void configure() {
854 ThrowingProviderBinder.create(binder())
855 .bind(RemoteProvider.class, new TypeLiteral<List<String>>() {})
856 .to(new RemoteProvider<List<String>>() {
857 public List<String> get() {
limpbizkite451ef72007-12-19 01:15:59 +0000858 return Arrays.asList("A", "B");
859 }
860 });
861 }
862 });
863
864 Key<RemoteProvider<List<String>>> key
865 = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
sberlinee446ca2010-10-24 21:36:39 +0000866 assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
867 }
868
sberlin488284d2010-11-17 14:27:41 +0000869 public void testBindingToInterfaceWithGeneric_Provides() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000870 providesInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500871 @Override
sberlinee446ca2010-10-24 21:36:39 +0000872 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +0000873 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +0000874 }
875
876 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +0000877 @CheckedProvides(RemoteProvider.class)
sberlinee446ca2010-10-24 21:36:39 +0000878 List<String> foo() throws RemoteException {
879 return Arrays.asList("A", "B");
880 }
881 });
882
883 Key<RemoteProvider<List<String>>> key
884 = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
885 assertEquals(Arrays.asList("A", "B"), providesInjector.getInstance(key).get());
886 }
887
Sam Berlin8557c772012-03-01 14:21:26 -0500888 public void testBindingToInterfaceWithGeneric_Cxtor() throws Exception {
889 cxtorInjector = Guice.createInjector(new AbstractModule() {
890 @Override
891 protected void configure() {
892 ThrowingProviderBinder.create(binder())
893 .bind(RemoteProvider.class, new TypeLiteral<List<String>>() {})
Sam Berline6abeff2012-05-27 13:39:59 -0400894 .providing(new TypeLiteral<ThrowingArrayList<String>>() {});
Sam Berlin8557c772012-03-01 14:21:26 -0500895 }
896 });
897
898 Key<RemoteProvider<List<String>>> key
899 = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
900 assertEquals(Arrays.asList(), cxtorInjector.getInstance(key).get());
901 }
902
Sam Berline6abeff2012-05-27 13:39:59 -0400903 private static class ThrowingArrayList<T> extends ArrayList<T> {
904 @SuppressWarnings("unused")
905 @ThrowingInject
906 ThrowingArrayList() {}
907 }
908
sberlinee446ca2010-10-24 21:36:39 +0000909 public void testProviderMethodWithWrongException() {
910 try {
911 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500912 @Override
sberlinee446ca2010-10-24 21:36:39 +0000913 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +0000914 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +0000915 }
916
917 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +0000918 @CheckedProvides(RemoteProvider.class)
sberlinee446ca2010-10-24 21:36:39 +0000919 String foo() throws InterruptedException {
920 return null;
921 }
922 });
923 fail();
924 } catch(CreationException ce) {
sberlin488284d2010-11-17 14:27:41 +0000925 assertEquals(InterruptedException.class.getName()
926 + " is not compatible with the exceptions (["
927 + RemoteException.class + ", " + BindException.class
928 + "]) declared in the CheckedProvider interface ("
929 + RemoteProvider.class.getName()
930 + ")",
sberlinee446ca2010-10-24 21:36:39 +0000931 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
932 }
933 }
934
Sam Berlin8557c772012-03-01 14:21:26 -0500935 public void testCxtorWithWrongException() {
936 try {
937 Guice.createInjector(new AbstractModule() {
938 @Override
939 protected void configure() {
940 ThrowingProviderBinder.create(binder())
941 .bind(RemoteProvider.class, Foo.class)
942 .providing(WrongExceptionFoo.class);
943 }
944 });
945 fail();
946 } catch (CreationException ce) {
947 assertEquals(InterruptedException.class.getName()
948 + " is not compatible with the exceptions (["
949 + RemoteException.class + ", " + BindException.class
950 + "]) declared in the CheckedProvider interface ("
951 + RemoteProvider.class.getName()
952 + ")",
953 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
954 }
955 }
956
957 static class WrongExceptionFoo implements Foo {
958 @SuppressWarnings("unused")
Sam Berline6abeff2012-05-27 13:39:59 -0400959 @ThrowingInject
Sam Berlin8557c772012-03-01 14:21:26 -0500960 public WrongExceptionFoo() throws InterruptedException {
961 }
962
963 @Override
964 public String s() { return null; }
965 }
966
sberlin488284d2010-11-17 14:27:41 +0000967 public void testProviderMethodWithSubclassOfExceptionIsOk() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +0000968 providesInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -0500969 @Override
sberlinee446ca2010-10-24 21:36:39 +0000970 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +0000971 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +0000972 }
973
974 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +0000975 @CheckedProvides(RemoteProvider.class)
Sam Berlin8557c772012-03-01 14:21:26 -0500976 Foo foo() throws AccessException {
sberlinee446ca2010-10-24 21:36:39 +0000977 throw new AccessException("boo!");
978 }
979 });
980
Sam Berlin8557c772012-03-01 14:21:26 -0500981 RemoteProvider<Foo> remoteProvider =
982 providesInjector.getInstance(Key.get(remoteProviderOfFoo));
sberlinee446ca2010-10-24 21:36:39 +0000983
984 try {
985 remoteProvider.get();
986 fail();
987 } catch (RemoteException expected) {
988 assertTrue(expected instanceof AccessException);
989 assertEquals("boo!", expected.getMessage());
990 }
991 }
992
Sam Berlin8557c772012-03-01 14:21:26 -0500993 public void testCxtorWithSubclassOfExceptionIsOk() throws Exception {
994 cxtorInjector = Guice.createInjector(new AbstractModule() {
995 @Override
996 protected void configure() {
997 ThrowingProviderBinder.create(binder())
998 .bind(RemoteProvider.class, Foo.class)
999 .providing(SubclassExceptionFoo.class);
1000 }
1001 });
1002
1003 RemoteProvider<Foo> remoteProvider =
1004 cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
1005
1006 try {
1007 remoteProvider.get();
1008 fail();
1009 } catch (RemoteException expected) {
1010 assertTrue(expected instanceof AccessException);
1011 assertEquals("boo!", expected.getMessage());
1012 }
1013 }
1014
1015 static class SubclassExceptionFoo implements Foo {
Sam Berline6abeff2012-05-27 13:39:59 -04001016 @ThrowingInject
Sam Berlin8557c772012-03-01 14:21:26 -05001017 public SubclassExceptionFoo() throws AccessException {
1018 throw new AccessException("boo!");
1019 }
1020
1021 @Override
1022 public String s() { return null; }
1023 }
1024
1025 public void testProviderMethodWithSuperclassExceptionFails() {
sberlinee446ca2010-10-24 21:36:39 +00001026 try {
1027 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -05001028 @Override
sberlinee446ca2010-10-24 21:36:39 +00001029 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +00001030 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +00001031 }
1032
1033 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +00001034 @CheckedProvides(RemoteProvider.class)
Sam Berlin8557c772012-03-01 14:21:26 -05001035 Foo foo() throws IOException {
sberlinee446ca2010-10-24 21:36:39 +00001036 return null;
1037 }
1038 });
1039 fail();
1040 } catch(CreationException ce) {
sberlin488284d2010-11-17 14:27:41 +00001041 assertEquals(IOException.class.getName()
1042 + " is not compatible with the exceptions (["
1043 + RemoteException.class + ", " + BindException.class
1044 + "]) declared in the CheckedProvider interface ("
1045 + RemoteProvider.class.getName()
1046 + ")",
sberlinee446ca2010-10-24 21:36:39 +00001047 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1048 }
1049 }
1050
Sam Berlin8557c772012-03-01 14:21:26 -05001051 public void testCxtorWithSuperclassExceptionFails() {
1052 try {
1053 Guice.createInjector(new AbstractModule() {
1054 @Override
1055 protected void configure() {
1056 ThrowingProviderBinder.create(binder())
1057 .bind(RemoteProvider.class, Foo.class)
1058 .providing(SuperclassExceptionFoo.class);
1059 }
1060 });
1061 fail();
1062 } catch (CreationException ce) {
1063 assertEquals(IOException.class.getName()
1064 + " is not compatible with the exceptions (["
1065 + RemoteException.class + ", " + BindException.class
1066 + "]) declared in the CheckedProvider interface ("
1067 + RemoteProvider.class.getName()
1068 + ")",
1069 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1070 }
1071 }
1072
1073 static class SuperclassExceptionFoo implements Foo {
1074 @SuppressWarnings("unused")
Sam Berline6abeff2012-05-27 13:39:59 -04001075 @ThrowingInject
Sam Berlin8557c772012-03-01 14:21:26 -05001076 public SuperclassExceptionFoo() throws IOException {
1077 }
1078
1079 @Override
1080 public String s() { return null; }
1081 }
1082
sberlin488284d2010-11-17 14:27:41 +00001083 public void testProviderMethodWithRuntimeExceptionsIsOk() throws Exception {
sberlinee446ca2010-10-24 21:36:39 +00001084 providesInjector = Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -05001085 @Override
sberlinee446ca2010-10-24 21:36:39 +00001086 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +00001087 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +00001088 }
1089
1090 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +00001091 @CheckedProvides(RemoteProvider.class)
Sam Berlin8557c772012-03-01 14:21:26 -05001092 Foo foo() throws RuntimeException {
sberlinee446ca2010-10-24 21:36:39 +00001093 throw new RuntimeException("boo!");
1094 }
1095 });
1096
Sam Berlin8557c772012-03-01 14:21:26 -05001097 RemoteProvider<Foo> remoteProvider =
1098 providesInjector.getInstance(Key.get(remoteProviderOfFoo));
sberlinee446ca2010-10-24 21:36:39 +00001099
1100 try {
1101 remoteProvider.get();
1102 fail();
1103 } catch (RuntimeException expected) {
1104 assertEquals("boo!", expected.getCause().getMessage());
1105 }
1106 }
1107
Sam Berlin8557c772012-03-01 14:21:26 -05001108 public void testCxtorWithRuntimeExceptionsIsOk() throws Exception {
1109 cxtorInjector = Guice.createInjector(new AbstractModule() {
1110 @Override
1111 protected void configure() {
1112 ThrowingProviderBinder.create(binder())
1113 .bind(RemoteProvider.class, Foo.class)
1114 .providing(RuntimeExceptionFoo.class);
1115 }
1116 });
1117
1118 RemoteProvider<Foo> remoteProvider =
1119 cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
1120
1121 try {
1122 remoteProvider.get();
1123 fail();
1124 } catch (RuntimeException expected) {
1125 assertEquals("boo!", expected.getCause().getMessage());
1126 }
1127 }
1128
1129 static class RuntimeExceptionFoo implements Foo {
Sam Berline6abeff2012-05-27 13:39:59 -04001130 @ThrowingInject
Sam Berlin8557c772012-03-01 14:21:26 -05001131 public RuntimeExceptionFoo() throws RuntimeException {
1132 throw new RuntimeException("boo!");
1133 }
1134
1135 @Override
1136 public String s() { return null; }
1137 }
1138
sberlin488284d2010-11-17 14:27:41 +00001139 private static class SubBindException extends BindException {}
1140
sberlinee446ca2010-10-24 21:36:39 +00001141 public void testProviderMethodWithManyExceptions() {
1142 try {
1143 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -05001144 @Override
sberlinee446ca2010-10-24 21:36:39 +00001145 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +00001146 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +00001147 }
1148
1149 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +00001150 @CheckedProvides(RemoteProvider.class)
sberlinee446ca2010-10-24 21:36:39 +00001151 String foo() throws InterruptedException, RuntimeException, RemoteException,
sberlin488284d2010-11-17 14:27:41 +00001152 AccessException, TooManyListenersException,
1153 BindException, SubBindException {
sberlinee446ca2010-10-24 21:36:39 +00001154 return null;
1155 }
1156 });
1157 fail();
1158 } catch(CreationException ce) {
1159 // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK.
1160 List<Message> errors = ImmutableList.copyOf(ce.getErrorMessages());
sberlin488284d2010-11-17 14:27:41 +00001161 assertEquals(InterruptedException.class.getName()
1162 + " is not compatible with the exceptions (["
1163 + RemoteException.class + ", " + BindException.class
1164 + "]) declared in the CheckedProvider interface ("
1165 + RemoteProvider.class.getName()
1166 + ")",
sberlinee446ca2010-10-24 21:36:39 +00001167 errors.get(0).getMessage());
sberlin488284d2010-11-17 14:27:41 +00001168 assertEquals(TooManyListenersException.class.getName()
1169 + " is not compatible with the exceptions (["
1170 + RemoteException.class + ", " + BindException.class
1171 + "]) declared in the CheckedProvider interface ("
1172 + RemoteProvider.class.getName()
1173 + ")",
sberlinee446ca2010-10-24 21:36:39 +00001174 errors.get(1).getMessage());
1175 assertEquals(2, errors.size());
1176 }
1177 }
1178
Sam Berlin8557c772012-03-01 14:21:26 -05001179 public void testCxtorWithManyExceptions() {
1180 try {
1181 Guice.createInjector(new AbstractModule() {
1182 @Override
1183 protected void configure() {
1184 ThrowingProviderBinder.create(binder())
1185 .bind(RemoteProvider.class, Foo.class)
1186 .providing(ManyExceptionFoo.class);
1187 }
1188 });
1189 fail();
1190 } catch (CreationException ce) {
1191 // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK.
1192 List<Message> errors = ImmutableList.copyOf(ce.getErrorMessages());
1193 assertEquals(InterruptedException.class.getName()
1194 + " is not compatible with the exceptions (["
1195 + RemoteException.class + ", " + BindException.class
1196 + "]) declared in the CheckedProvider interface ("
1197 + RemoteProvider.class.getName()
1198 + ")",
1199 errors.get(0).getMessage());
1200 assertEquals(TooManyListenersException.class.getName()
1201 + " is not compatible with the exceptions (["
1202 + RemoteException.class + ", " + BindException.class
1203 + "]) declared in the CheckedProvider interface ("
1204 + RemoteProvider.class.getName()
1205 + ")",
1206 errors.get(1).getMessage());
1207 assertEquals(2, errors.size());
1208 }
1209 }
1210
1211 static class ManyExceptionFoo implements Foo {
1212 @SuppressWarnings("unused")
Sam Berline6abeff2012-05-27 13:39:59 -04001213 @ThrowingInject
Sam Berlin8557c772012-03-01 14:21:26 -05001214 public ManyExceptionFoo()
1215 throws InterruptedException,
1216 RuntimeException,
1217 RemoteException,
1218 AccessException,
1219 TooManyListenersException,
1220 BindException,
1221 SubBindException {
1222 }
1223
1224 @Override
1225 public String s() { return null; }
1226 }
1227
sberlinee446ca2010-10-24 21:36:39 +00001228 public void testMoreTypeParameters() {
1229 try {
1230 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -05001231 @Override
sberlinee446ca2010-10-24 21:36:39 +00001232 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +00001233 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +00001234 }
1235
1236 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +00001237 @CheckedProvides(TooManyTypeParameters.class)
sberlinee446ca2010-10-24 21:36:39 +00001238 String foo() {
1239 return null;
1240 }
1241 });
1242 fail();
1243 } catch(CreationException ce) {
1244 assertEquals(TooManyTypeParameters.class.getName() + " has more than one generic type parameter: [T, P]",
1245 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1246 }
1247 }
1248
1249 public void testWrongThrowingProviderType() {
1250 try {
1251 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -05001252 @Override
sberlinee446ca2010-10-24 21:36:39 +00001253 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +00001254 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +00001255 }
1256
1257 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +00001258 @CheckedProvides(WrongThrowingProviderType.class)
sberlinee446ca2010-10-24 21:36:39 +00001259 String foo() {
1260 return null;
1261 }
1262 });
1263 fail();
1264 } catch(CreationException ce) {
1265 assertEquals(WrongThrowingProviderType.class.getName()
sberlin488284d2010-11-17 14:27:41 +00001266 + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider "
sberlinee446ca2010-10-24 21:36:39 +00001267 + "(java.lang.String) is not a generic type",
1268 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1269 }
1270 }
1271
1272 public void testOneMethodThatIsntGet() {
1273 try {
1274 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -05001275 @Override
sberlinee446ca2010-10-24 21:36:39 +00001276 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +00001277 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +00001278 }
1279
1280 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +00001281 @CheckedProvides(OneNoneGetMethod.class)
sberlinee446ca2010-10-24 21:36:39 +00001282 String foo() {
1283 return null;
1284 }
1285 });
1286 fail();
1287 } catch(CreationException ce) {
1288 assertEquals(OneNoneGetMethod.class.getName()
sberlindfee9fd2010-10-30 14:15:06 +00001289 + " may not declare any new methods, but declared " + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]),
sberlinee446ca2010-10-24 21:36:39 +00001290 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1291 }
1292 }
1293
1294 public void testManyMethods() {
1295 try {
1296 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -05001297 @Override
sberlinee446ca2010-10-24 21:36:39 +00001298 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +00001299 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +00001300 }
1301
1302 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +00001303 @CheckedProvides(ManyMethods.class)
sberlinee446ca2010-10-24 21:36:39 +00001304 String foo() {
1305 return null;
1306 }
1307 });
1308 fail();
1309 } catch(CreationException ce) {
1310 assertEquals(ManyMethods.class.getName()
1311 + " may not declare any new methods, but declared " + Arrays.asList(ManyMethods.class.getDeclaredMethods()),
1312 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1313 }
1314 }
1315
1316 public void testIncorrectPredefinedType_Bind() {
1317 try {
1318 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -05001319 @Override
sberlinee446ca2010-10-24 21:36:39 +00001320 protected void configure() {
1321 ThrowingProviderBinder.create(binder())
1322 .bind(StringRemoteProvider.class, Integer.class)
1323 .to(new StringRemoteProvider() {
Sam Berlin8557c772012-03-01 14:21:26 -05001324 public String get() {
sberlinee446ca2010-10-24 21:36:39 +00001325 return "A";
1326 }
1327 });
1328 }
1329 });
1330 fail();
1331 } catch(CreationException ce) {
1332 assertEquals(StringRemoteProvider.class.getName()
1333 + " expects the value type to be java.lang.String, but it was java.lang.Integer",
1334 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1335 }
1336 }
1337
1338 public void testIncorrectPredefinedType_Provides() {
1339 try {
1340 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -05001341 @Override
sberlinee446ca2010-10-24 21:36:39 +00001342 protected void configure() {
sberlin488284d2010-11-17 14:27:41 +00001343 install(ThrowingProviderBinder.forModule(this));
sberlinee446ca2010-10-24 21:36:39 +00001344 }
1345
1346 @SuppressWarnings("unused")
sberlin488284d2010-11-17 14:27:41 +00001347 @CheckedProvides(StringRemoteProvider.class)
sberlinee446ca2010-10-24 21:36:39 +00001348 Integer foo() {
1349 return null;
1350 }
1351 });
1352 fail();
1353 } catch(CreationException ce) {
1354 assertEquals(StringRemoteProvider.class.getName()
1355 + " expects the value type to be java.lang.String, but it was java.lang.Integer",
1356 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1357 }
1358 }
1359
sberlin488284d2010-11-17 14:27:41 +00001360 private static interface TooManyTypeParameters<T, P> extends CheckedProvider<T> {
sberlinee446ca2010-10-24 21:36:39 +00001361 }
1362
sberlin488284d2010-11-17 14:27:41 +00001363 private static interface WrongThrowingProviderType<T> extends CheckedProvider<String> {
sberlinee446ca2010-10-24 21:36:39 +00001364 }
1365
sberlin488284d2010-11-17 14:27:41 +00001366 private static interface OneNoneGetMethod<T> extends CheckedProvider<T> {
sberlinee446ca2010-10-24 21:36:39 +00001367 T bar();
1368 }
1369
sberlin488284d2010-11-17 14:27:41 +00001370 private static interface ManyMethods<T> extends CheckedProvider<T> {
sberlinee446ca2010-10-24 21:36:39 +00001371 T bar();
1372 String baz();
limpbizkite451ef72007-12-19 01:15:59 +00001373 }
sberlin488284d2010-11-17 14:27:41 +00001374
1375 public void testResultSerializes() throws Exception {
1376 Result result = Result.forValue("foo");
1377 result = Asserts.reserialize(result);
1378 assertEquals("foo", result.getOrThrow());
1379 }
1380
1381 public void testResultExceptionSerializes() throws Exception {
1382 Result result = Result.forException(new Exception("boo"));
1383 result = Asserts.reserialize(result);
1384 try {
1385 result.getOrThrow();
1386 fail();
1387 } catch(Exception ex) {
1388 assertEquals("boo", ex.getMessage());
1389 }
1390 }
1391
1392 public void testEarlyBindingError() {
1393 try {
1394 Guice.createInjector(new AbstractModule() {
Sam Berlin8557c772012-03-01 14:21:26 -05001395 @Override
sberlin488284d2010-11-17 14:27:41 +00001396 protected void configure() {
1397 ThrowingProviderBinder.create(binder())
1398 .bind(StringRemoteProvider.class, String.class)
1399 .to(FailingProvider.class);
1400 }
1401 });
1402 fail();
1403 } catch(CreationException ce) {
1404 assertEquals("Could not find a suitable constructor in " + FailingProvider.class.getName()
1405 + ". Classes must have either one (and only one) constructor annotated with @Inject"
1406 + " or a zero-argument constructor that is not private.",
1407 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1408 }
1409 }
1410
1411 private static class FailingProvider implements StringRemoteProvider {
1412 // no @Inject.
1413 @SuppressWarnings("unused")
1414 FailingProvider(Integer foo) {}
1415
1416 public String get() {
1417 return null;
1418 }
1419 }
Sam Berlin8557c772012-03-01 14:21:26 -05001420
1421 public void testNoInjectionPointForUsing() {
1422 try {
1423 Guice.createInjector(new AbstractModule() {
1424 @Override
1425 protected void configure() {
1426 ThrowingProviderBinder.create(binder())
1427 .bind(RemoteProvider.class, Foo.class)
1428 .providing(InvalidFoo.class);
1429 }
1430 });
1431 fail();
1432 } catch (CreationException ce) {
1433 assertEquals("Could not find a suitable constructor in " + InvalidFoo.class.getName()
1434 + ". Classes must have either one (and only one) constructor annotated with "
Sam Berline6abeff2012-05-27 13:39:59 -04001435 + "@ThrowingInject.",
Sam Berlin8557c772012-03-01 14:21:26 -05001436 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1437 }
1438 }
1439
1440 static class InvalidFoo implements Foo {
1441 public InvalidFoo(String dep) {
1442 }
1443
1444 @Override public String s() { return null; }
1445 }
1446
Sam Berline6abeff2012-05-27 13:39:59 -04001447 public void testNoThrowingInject() {
1448 try {
1449 Guice.createInjector(new AbstractModule() {
1450 @Override
1451 protected void configure() {
1452 ThrowingProviderBinder.create(binder())
1453 .bind(RemoteProvider.class, Foo.class)
1454 .providing(NormalInjectableFoo.class);
1455 }
1456 });
1457 fail();
1458 } catch (CreationException ce) {
1459 assertEquals("Could not find a suitable constructor in " + NormalInjectableFoo.class.getName()
1460 + ". Classes must have either one (and only one) constructor annotated with "
1461 + "@ThrowingInject.",
1462 Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
1463 }
1464 }
1465
1466 static class NormalInjectableFoo implements Foo {
1467 @Inject
1468 public NormalInjectableFoo() {
1469 }
1470
1471 @Override public String s() { return null; }
1472 }
1473
Sam Berlin8b7aaec2012-05-27 13:42:13 -04001474 public void testProvisionExceptionOnDependenciesOfCxtor() throws Exception {
1475 Injector injector = Guice.createInjector(new AbstractModule() {
1476 @Override
1477 protected void configure() {
1478 ThrowingProviderBinder.create(binder())
1479 .bind(RemoteProvider.class, Foo.class)
1480 .providing(ProvisionExceptionFoo.class);
1481 bindScope(BadScope.class, new Scope() {
1482 @Override
1483 public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
1484 return new Provider<T>() {
1485 @Override
1486 public T get() {
1487 throw new OutOfScopeException("failure");
1488 }
1489 };
1490 }
1491 });
1492 }
1493 });
1494
1495 try {
1496 injector.getInstance(Key.get(remoteProviderOfFoo)).get();
1497 fail();
1498 } catch(ProvisionException pe) {
1499 assertEquals(2, pe.getErrorMessages().size());
1500 List<Message> messages = Lists.newArrayList(pe.getErrorMessages());
1501 assertEquals("Error in custom provider, com.google.inject.OutOfScopeException: failure",
1502 messages.get(0).getMessage());
1503 assertEquals("Error in custom provider, com.google.inject.OutOfScopeException: failure",
1504 messages.get(1).getMessage());
1505 }
1506 }
1507
1508 @ScopeAnnotation
1509 @Target(ElementType.TYPE)
1510 @Retention(RetentionPolicy.RUNTIME)
1511 private @interface BadScope { }
1512
1513 @BadScope private static class Unscoped1 {}
1514 @BadScope private static class Unscoped2 {}
1515
1516 static class ProvisionExceptionFoo implements Foo {
1517 @ThrowingInject
1518 public ProvisionExceptionFoo(Unscoped1 a, Unscoped2 b) {
1519 }
1520
1521 @Override public String s() { return null; }
1522 }
1523
Sam Berlin8557c772012-03-01 14:21:26 -05001524 public void testUsingDoesntClashWithBindingsOfSameType() throws Exception {
1525 cxtorInjector = Guice.createInjector(new AbstractModule() {
1526 @Override
1527 protected void configure() {
1528 ThrowingProviderBinder.create(binder())
1529 .bind(RemoteProvider.class, Foo.class)
1530 .providing(MockFoo.class);
1531 bind(Foo.class).to(MockFoo.class);
1532 bind(MockFoo.class).to(SubMockFoo.class);
1533 }
1534 });
1535
1536 RemoteProvider<Foo> remoteProvider =
1537 cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
1538 Foo providerGot = remoteProvider.get();
1539 Foo fooGot = cxtorInjector.getInstance(Foo.class);
1540 Foo mockGot = cxtorInjector.getInstance(MockFoo.class);
1541
1542 assertEquals(MockFoo.class, providerGot.getClass());
1543 assertEquals(SubMockFoo.class, fooGot.getClass());
1544 assertEquals(SubMockFoo.class, mockGot.getClass());
1545 }
1546
1547 static class SubMockFoo extends MockFoo {
1548 public SubMockFoo() throws RemoteException, BindException {
1549 }
1550
1551 }
limpbizkite451ef72007-12-19 01:15:59 +00001552}