/* * Copyright 2013 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.inject.client.multibindings; import static com.google.gwt.inject.client.multibindings.GinMapBinder.newMapBinder; import com.google.gwt.core.client.GWT; import com.google.gwt.inject.client.AbstractGinModule; import com.google.gwt.inject.client.GinModules; import com.google.gwt.inject.client.Ginjector; import com.google.gwt.inject.client.multibindings.TestTypes.AboutPlaceProvider; import com.google.gwt.inject.client.multibindings.TestTypes.HomePlaceProvider; import com.google.gwt.inject.client.multibindings.TestTypes.Place; import com.google.gwt.inject.client.multibindings.TestTypes.ProviderForXImpl2; import com.google.gwt.inject.client.multibindings.TestTypes.X; import com.google.gwt.inject.client.multibindings.TestTypes.XImpl1; import com.google.gwt.inject.client.multibindings.TestTypes.XImpl2; import com.google.gwt.inject.client.multibindings.TestTypes.XWithGenerics; import com.google.gwt.inject.client.multibindings.TestTypes.Y; import com.google.gwt.inject.client.multibindings.TestTypes.YImpl; import com.google.gwt.junit.client.GWTTestCase; import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; import com.google.inject.name.Named; import com.google.inject.name.Names; import java.util.Iterator; import java.util.Map; import java.util.Set; public class GinMapBinderTest extends GWTTestCase { public static class GinModuleWithNoBinding extends AbstractGinModule { @Override protected void configure() { newMapBinder(binder(), String.class, X.class); } } @GinModules(GinModuleWithNoBinding.class) public interface NoBindingGinjector extends Ginjector { Map<String, X> getMap(); } public void testInject_empty() throws Exception { NoBindingGinjector injector = GWT.create(NoBindingGinjector.class); Map<String, X> map = injector.getMap(); assertTrue(map.isEmpty()); } public static class GinModuleWithXY extends AbstractGinModule { @Override protected void configure() { newMapBinder(binder(), String.class, X.class).addBinding("1").to(XImpl1.class); newMapBinder(binder(), String.class, Y.class).addBinding("1").to(YImpl.class); } } public static class GinModuleWithMoreX extends AbstractGinModule { @Override protected void configure() { GinMapBinder<String, X> mapBinder = newMapBinder(binder(), String.class, X.class); mapBinder.addBinding("2").to(XImpl2.class); mapBinder.addBinding("3").to(XImpl1.class); TypeLiteral<XWithGenerics<YImpl>> x3 = new TypeLiteral<XWithGenerics<YImpl>>() {}; mapBinder.addBinding("4").to(x3); } } @GinModules({GinModuleWithXY.class, GinModuleWithMoreX.class}) public interface MapGinjector extends Ginjector { Map<String, X> getMapX(); Map<String, Y> getMapY(); Map<String, Provider<X>> getProviderMapX(); } public void testInject() throws Exception { MapGinjector injector = GWT.create(MapGinjector.class); Map<String, X> mapX = injector.getMapX(); assertEquals(4, mapX.size()); assertTrue(mapX.get("1") instanceof XImpl1); assertTrue(mapX.get("2") instanceof XImpl2); assertTrue(mapX.get("3") instanceof XImpl1); assertTrue(mapX.get("4") instanceof XWithGenerics<?>); assertTrue(((XWithGenerics<?>) mapX.get("4")).object instanceof YImpl); Map<String, Y> mapY = injector.getMapY(); assertEquals(1, mapY.size()); assertTrue(mapY.get("1") instanceof YImpl); } public void testInject_mapProvider() throws Exception { MapGinjector injector = GWT.create(MapGinjector.class); Map<String, Provider<X>> mapX = injector.getProviderMapX(); assertEquals(4, mapX.size()); assertTrue(mapX.get("1").get() instanceof XImpl1); assertTrue(mapX.get("2").get() instanceof XImpl2); assertTrue(mapX.get("3").get() instanceof XImpl1); assertTrue(mapX.get("4").get() instanceof XWithGenerics<?>); assertTrue(((XWithGenerics<?>) mapX.get("4").get()).object instanceof YImpl); } public void testInject_sameMapTwice() throws Exception { MapGinjector injector = GWT.create(MapGinjector.class); Map<String, X> map1 = injector.getMapX(); Map<String, X> map2 = injector.getMapX(); assertEquals(map1.size(), map2.size()); assertTrue(map2.get("1") instanceof XImpl1); assertNotSame(map1.get("1"), map2.get("1")); assertTrue(map2.get("2") instanceof XImpl2); assertNotSame(map1.get("2"), map2.get("2")); // Provider maps are safe to reuse assertSame(injector.getProviderMapX(), injector.getProviderMapX()); } public static class GinModuleWithScopedX extends AbstractGinModule { @Override protected void configure() { newMapBinder(binder(), String.class, X.class) .addBinding("2").to(XImpl1.class).in(Singleton.class); } } @GinModules({GinModuleWithXY.class, GinModuleWithScopedX.class}) public interface MapGinjectorWithScope extends Ginjector { Map<String, X> getMap(); } public void testInject_sameMapTwiceWithScope() throws Exception { MapGinjectorWithScope injector = GWT.create(MapGinjectorWithScope.class); Map<String, X> map1 = injector.getMap(); Map<String, X> map2 = injector.getMap(); assertEquals(map1.size(), map2.size()); assertNotSame(map1.get("1"), map2.get("1")); assertSame(map1.get("2"), map2.get("2")); } public static class GinModuleWithKeyProviders extends AbstractGinModule { @Override protected void configure() { GinMapBinder.newMapBinder(binder(), Place.class, X.class) .addBinding(HomePlaceProvider.class).to(XImpl1.class); GinMapBinder.newMapBinder(binder(), Place.class, X.class) .addBinding(AboutPlaceProvider.class).to(XImpl2.class); } } @GinModules(GinModuleWithKeyProviders.class) public interface PlacesGinjector extends Ginjector { Map<Place, X> getMap(); } public void testInject_keyProvider() throws Exception { PlacesGinjector injector = GWT.create(PlacesGinjector.class); Map<Place, X> map = injector.getMap(); assertEquals(2, map.size()); assertTrue(map.get(new Place("home")) instanceof XImpl1); assertTrue(map.get(new Place("about")) instanceof XImpl2); } public static class GinModuleWithDuplicateBinding extends AbstractGinModule { @Override protected void configure() { install(new GinModuleWithXY()); newMapBinder(binder(), String.class, X.class).addBinding("1").to(XImpl2.class); } } @GinModules(GinModuleWithDuplicateBinding.class) public interface DoubleBindingGinjector extends Ginjector { Map<String, X> getMapX(); Map<String, Provider<X>> getProviderMapX(); } public void testInject_dontPermitDuplicates() { DoubleBindingGinjector injector = GWT.create(DoubleBindingGinjector.class); try { injector.getMapX(); fail("should have thrown exception"); } catch (IllegalStateException e) { assertTrue(e.toString().contains("duplicate")); } try { injector.getProviderMapX(); fail("should have thrown exception"); } catch (IllegalStateException e) { assertTrue(e.toString().contains("duplicate")); } } public static class GinModuleForPermittingDuplicate extends AbstractGinModule { @Override protected void configure() { newMapBinder(binder(), String.class, X.class).permitDuplicates(); newMapBinder(binder(), String.class, X.class).permitDuplicates(); // multiple calls are OK } } @GinModules(GinModuleForPermittingDuplicate.class) public interface MultimapGinjector extends DoubleBindingGinjector { Map<String, Set<X>> getMultimapX(); Map<String, Set<Provider<X>>> getProviderMultimapX(); } public void testInject_multimap() throws Exception { MultimapGinjector injector = GWT.create(MultimapGinjector.class); Map<String, Set<X>> mapX = injector.getMultimapX(); assertEquals(1, mapX.size()); Iterator<X> iterator = mapX.get("1").iterator(); assertTrue(iterator.next() instanceof XImpl1); assertTrue(iterator.next() instanceof XImpl2); } public void testInject_providerMultimap() throws Exception { MultimapGinjector injector = GWT.create(MultimapGinjector.class); Map<String, Set<Provider<X>>> mapX = injector.getProviderMultimapX(); assertEquals(1, mapX.size()); Iterator<Provider<X>> iterator = mapX.get("1").iterator(); assertTrue(iterator.next().get() instanceof XImpl1); assertTrue(iterator.next().get() instanceof XImpl2); } public void testInject_sameMultimapTwice() throws Exception { MultimapGinjector injector = GWT.create(MultimapGinjector.class); Map<String, Set<X>> map1 = injector.getMultimapX(); Map<String, Set<X>> map2 = injector.getMultimapX(); assertEquals(map1.size(), map2.size()); Iterator<X> iterator1 = map1.get("1").iterator(); Iterator<X> iterator2 = map2.get("1").iterator(); X next1 = iterator1.next(); X next2 = iterator2.next(); assertTrue(next1 instanceof XImpl1); assertTrue(next2 instanceof XImpl1); assertNotSame(next1, next2); next1 = iterator1.next(); next2 = iterator2.next(); assertTrue(next1 instanceof XImpl2); assertTrue(next2 instanceof XImpl2); assertNotSame(next1, next2); // Provider maps are safe to reuse assertSame(injector.getProviderMultimapX(), injector.getProviderMultimapX()); } public static class GinModuleWithRegularBind extends AbstractGinModule { @Override protected void configure() { newMapBinder(binder(), String.class, X.class).addBinding("1").to(XImpl1.class); bind(X.class).to(XImpl2.class); } } @GinModules(GinModuleWithRegularBind.class) public interface GinjectorWithRegularBind extends Ginjector { Map<String, X> getMapX(); X getX(); } public void testInject_sameInterfaceBoundWithBothRegularAndMapBind() throws Exception { GinjectorWithRegularBind injector = GWT.create(GinjectorWithRegularBind.class); assertTrue(injector.getMapX().get("1") instanceof XImpl1); assertTrue(injector.getX() instanceof XImpl2); } public static class GinModuleWithProvider extends AbstractGinModule { @Override protected void configure() { newMapBinder(binder(), String.class, X.class) .addBinding("P2").toProvider(ProviderForXImpl2.class); } } @GinModules({GinModuleWithXY.class, GinModuleWithProvider.class}) public interface GinjectorWithProvider extends Ginjector { Map<String, X> getMapX(); } public void testInject_valueBoundWithProvider() throws Exception { GinjectorWithProvider injector = GWT.create(GinjectorWithProvider.class); Map<String, X> mapX = injector.getMapX(); assertEquals(2, mapX.size()); assertTrue(mapX.get("1") instanceof XImpl1); assertTrue(mapX.get("P2") instanceof XImpl2); } public static class GinModuleWithAnnotations extends AbstractGinModule { @Override protected void configure() { GinMapBinder<String, X> mapBinder = newMapBinder(binder(), String.class, X.class); mapBinder.addBinding("1").to(XImpl1.class); mapBinder.addBinding("2").to(XImpl2.class); GinMapBinder<String, X> mapBinderA = newMapBinder(binder(), String.class, X.class, Names.named("a")); mapBinderA.addBinding("1").to(XImpl1.class); mapBinderA.addBinding("2").to(XImpl1.class); GinMapBinder<String, X> mapBinderB = newMapBinder(binder(), String.class, X.class, Names.named("b")); mapBinderB.addBinding("1").to(XImpl2.class); mapBinderB.addBinding("2").to(XImpl2.class); } } @GinModules(GinModuleWithAnnotations.class) public interface GinjectorWithAnnotations extends Ginjector { Map<String, X> getMapX(); @Named("a") Map<String, X> getMapXa(); @Named("b") Map<String, X> getMapXb(); } public void testInject_annotated() throws Exception { GinjectorWithAnnotations injector = GWT.create(GinjectorWithAnnotations.class); Map<String, X> mapX = injector.getMapX(); assertEquals(2, mapX.size()); assertTrue(mapX.get("1") instanceof XImpl1); assertTrue(mapX.get("2") instanceof XImpl2); Map<String, X> mapXa = injector.getMapXa(); assertEquals(2, mapXa.size()); assertTrue(mapXa.get("1") instanceof XImpl1); assertTrue(mapXa.get("2") instanceof XImpl1); Map<String, X> mapXb = injector.getMapXb(); assertEquals(2, mapXb.size()); assertTrue(mapXb.get("1") instanceof XImpl2); assertTrue(mapXb.get("2") instanceof XImpl2); } @Override public String getModuleName() { return "com.google.gwt.inject.InjectTest"; } }