15a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit/**
25a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * Copyright (C) 2008 Google Inc.
35a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit *
45a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * Licensed under the Apache License, Version 2.0 (the "License");
55a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * you may not use this file except in compliance with the License.
65a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * You may obtain a copy of the License at
75a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit *
85a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * http://www.apache.org/licenses/LICENSE-2.0
95a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit *
105a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * Unless required by applicable law or agreed to in writing, software
115a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * distributed under the License is distributed on an "AS IS" BASIS,
125a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * See the License for the specific language governing permissions and
145a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * limitations under the License.
155a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit */
165a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
172e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberpackage com.google.inject.util;
185a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
192e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport static com.google.inject.Asserts.asModuleChain;
20eab76471fbc2118a3c07d103d4b5548e153ed9e7limpbizkitimport static com.google.inject.Asserts.assertContains;
215a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkitimport static com.google.inject.Guice.createInjector;
225a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkitimport static com.google.inject.name.Names.named;
2354da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport static java.lang.annotation.ElementType.METHOD;
24b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport static java.lang.annotation.ElementType.TYPE;
25b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport static java.lang.annotation.RetentionPolicy.RUNTIME;
2619873c5c408e622cba43fe07614611062106057csberlin
27d9c913acca55023ef5d76a32c3d4a51ee6b420cbsberlinimport com.google.common.base.Objects;
2854da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport com.google.common.collect.ImmutableSet;
292e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.AbstractModule;
302e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.Binder;
3154da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport com.google.inject.Binding;
322e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.CreationException;
332e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.Exposed;
342e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.Guice;
352e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.Injector;
362e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.Key;
372e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.Module;
382e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.PrivateModule;
392e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.Provider;
402e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.Provides;
412e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.Scope;
422e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruberimport com.google.inject.ScopeAnnotation;
43ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlinimport com.google.inject.Stage;
4419873c5c408e622cba43fe07614611062106057csberlinimport com.google.inject.name.Named;
4554da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport com.google.inject.name.Names;
4654da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport com.google.inject.spi.InjectionPoint;
4754da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport com.google.inject.spi.ModuleAnnotatedMethodScanner;
48b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
49b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport junit.framework.TestCase;
50b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
5154da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport java.lang.annotation.Annotation;
5254da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport java.lang.annotation.Documented;
5397a51ffff130b192162f5a445762751998208799limpbizkitimport java.lang.annotation.Retention;
5497a51ffff130b192162f5a445762751998208799limpbizkitimport java.lang.annotation.Target;
555a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkitimport java.util.Date;
5654da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport java.util.Set;
57edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkitimport java.util.concurrent.atomic.AtomicReference;
585a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
595a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit/**
605a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit * @author sberlin@gmail.com (Sam Berlin)
615a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit */
625a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkitpublic class OverrideModuleTest extends TestCase {
635a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
645a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  private static final Key<String> key2 = Key.get(String.class, named("2"));
655a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  private static final Key<String> key3 = Key.get(String.class, named("3"));
665a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
675a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  private static final Module EMPTY_MODULE = new Module() {
685a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    public void configure(Binder binder) {}
695a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  };
705a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
715a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  public void testOverride() {
727e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Injector injector = createInjector(Modules.override(newModule("A")).with(newModule("B")));
737e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    assertEquals("B", injector.getInstance(String.class));
747e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit  }
755a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
767e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit  public void testOverrideMultiple() {
777e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Module module = Modules.override(newModule("A"), newModule(1), newModule(0.5f))
787e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit        .with(newModule("B"), newModule(2), newModule(1.5d));
797e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Injector injector = createInjector(module);
805a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("B", injector.getInstance(String.class));
817e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    assertEquals(2, injector.getInstance(Integer.class).intValue());
827e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    assertEquals(0.5f, injector.getInstance(Float.class));
837e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    assertEquals(1.5d, injector.getInstance(Double.class));
845a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  }
855a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
865a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  public void testOverrideUnmatchedTolerated() {
877e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Injector injector = createInjector(Modules.override(EMPTY_MODULE).with(newModule("B")));
885a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("B", injector.getInstance(String.class));
895a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  }
905a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
915a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  public void testOverrideConstant() {
925a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module original = new AbstractModule() {
9397a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
945a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bindConstant().annotatedWith(named("Test")).to("A");
955a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
965a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
975a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
985a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module replacements = new AbstractModule() {
9997a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
1005a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bindConstant().annotatedWith(named("Test")).to("B");
1015a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
1025a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
1035a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1047e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Injector injector = createInjector(Modules.override(original).with(replacements));
1055a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("B", injector.getInstance(Key.get(String.class, named("Test"))));
1065a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  }
1075a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1085a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  public void testGetProviderInModule() {
1095a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module original = new AbstractModule() {
11097a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
1115a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(String.class).toInstance("A");
1125a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(key2).toProvider(getProvider(String.class));
1135a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
1145a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
1155a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1167e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Injector injector = createInjector(Modules.override(original).with(EMPTY_MODULE));
1175a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("A", injector.getInstance(String.class));
1185a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("A", injector.getInstance(key2));
1195a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  }
1205a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1215a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  public void testOverrideWhatGetProviderProvided() {
1225a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module original = new AbstractModule() {
12397a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
1245a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(String.class).toInstance("A");
1255a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(key2).toProvider(getProvider(String.class));
1265a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
1275a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
1285a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1297e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Module replacements = newModule("B");
1305a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1317e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Injector injector = createInjector(Modules.override(original).with(replacements));
1325a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("B", injector.getInstance(String.class));
1335a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("B", injector.getInstance(key2));
1345a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  }
1355a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1365a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  public void testOverrideUsingOriginalsGetProvider() {
1375a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module original = new AbstractModule() {
13897a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
1395a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(String.class).toInstance("A");
1405a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(key2).toInstance("B");
1415a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
1425a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
1435a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1445a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module replacements = new AbstractModule() {
14597a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
1465a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(String.class).toProvider(getProvider(key2));
1475a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
1485a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
1495a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1507e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Injector injector = createInjector(Modules.override(original).with(replacements));
1515a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("B", injector.getInstance(String.class));
1525a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("B", injector.getInstance(key2));
1535a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  }
1545a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1555a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  public void testOverrideOfOverride() {
1565a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module original = new AbstractModule() {
15797a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
1585a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(String.class).toInstance("A1");
1595a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(key2).toInstance("A2");
1605a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(key3).toInstance("A3");
1615a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
1625a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
1635a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1645a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module replacements1 = new AbstractModule() {
16597a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
1665a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(String.class).toInstance("B1");
1675a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(key2).toInstance("B2");
1685a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
1695a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
1705a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1717e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Module overrides = Modules.override(original).with(replacements1);
1725a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1735a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module replacements2 = new AbstractModule() {
17497a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
1755a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(String.class).toInstance("C1");
1765a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(key3).toInstance("C3");
1775a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
1785a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
1795a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1807e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Injector injector = createInjector(Modules.override(overrides).with(replacements2));
1815a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("C1", injector.getInstance(String.class));
1825a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("B2", injector.getInstance(key2));
1835a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals("C3", injector.getInstance(key3));
1845a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  }
1855a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
1862e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber  static class OuterReplacementsModule extends AbstractModule {
1872e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    @Override protected void configure() {
1882e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      install(new InnerReplacementsModule());
1892e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    }
1902e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber  }
1912e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber  static class InnerReplacementsModule extends AbstractModule {
1922e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    @Override protected void configure() {
1932e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      bind(String.class).toInstance("B");
1942e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      bind(String.class).toInstance("C");
1952e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    }
1962e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber  }
1975a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  public void testOverridesTwiceFails() {
1987e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Module original = newModule("A");
1992e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    Module replacements = new OuterReplacementsModule();
2007e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Module module = Modules.override(original).with(replacements);
2015a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    try {
2025a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      createInjector(module);
2035a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      fail();
2045a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    } catch (CreationException expected) {
2052e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      assertContains(expected.getMessage(),
2062e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          "A binding to java.lang.String was already configured at "
2072e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber              + InnerReplacementsModule.class.getName(),
2082e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          asModuleChain(Modules.OverrideModule.class,
2092e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber              OuterReplacementsModule.class, InnerReplacementsModule.class),
2102e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          "at " + InnerReplacementsModule.class.getName(),
2112e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          asModuleChain(Modules.OverrideModule.class,
2122e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber              OuterReplacementsModule.class, InnerReplacementsModule.class));
2135a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    }
2145a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  }
2155a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
2165a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  public void testOverridesDoesntFixTwiceBoundInOriginal() {
2175a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module original = new AbstractModule() {
21897a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
2195a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(String.class).toInstance("A");
2205a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(String.class).toInstance("B");
2215a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
2225a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
2235a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
2245a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module replacements = new AbstractModule() {
22597a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
2265a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(String.class).toInstance("C");
2275a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
2285a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
2295a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
2307e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Module module = Modules.override(original).with(replacements);
2315a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    try {
2325a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      createInjector(module);
2335a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      fail();
2345a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    } catch (CreationException expected) {
2352e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      // The replacement comes first because we replace A with C,
2362e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      // then we encounter B and freak out.
2372e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      assertContains(expected.getMessage(),
2382e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          "1) A binding to java.lang.String was already configured at "
2392e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber              + replacements.getClass().getName(),
2402e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          asModuleChain(Modules.OverrideModule.class, replacements.getClass()),
2412e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          "at " + original.getClass().getName(),
2422e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          asModuleChain(Modules.OverrideModule.class, original.getClass()));
2435a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    }
2445a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  }
2455a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
246aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit  public void testStandardScopeAnnotation() {
247aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    final SingleUseScope scope = new SingleUseScope();
248aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
249aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    Module module = new AbstractModule() {
2502e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @Override protected void configure() {
251aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        bindScope(TestScopeAnnotation.class, scope);
252aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        bind(String.class).in(TestScopeAnnotation.class);
253aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit      }
254aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    };
255aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    assertFalse(scope.used);
256aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
257aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    Guice.createInjector(module);
258aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    assertTrue(scope.used);
259aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit  }
260aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
2615a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  public void testOverrideUntargettedBinding() {
2625a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module original = new AbstractModule() {
26397a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
2645a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(Date.class);
2655a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
2665a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
2675a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
2685a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    Module replacements = new AbstractModule() {
26997a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
2705a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit        bind(Date.class).toInstance(new Date(0));
2715a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit      }
2725a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    };
2735a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit
2747e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit    Injector injector = createInjector(Modules.override(original).with(replacements));
2755a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit    assertEquals(0, injector.getInstance(Date.class).getTime());
2765a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit  }
2777e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit
27897a51ffff130b192162f5a445762751998208799limpbizkit  public void testOverrideScopeAnnotation() {
27997a51ffff130b192162f5a445762751998208799limpbizkit    final Scope scope = new Scope() {
28097a51ffff130b192162f5a445762751998208799limpbizkit      public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
28197a51ffff130b192162f5a445762751998208799limpbizkit        throw new AssertionError("Should not be called");
28297a51ffff130b192162f5a445762751998208799limpbizkit      }
28397a51ffff130b192162f5a445762751998208799limpbizkit    };
28497a51ffff130b192162f5a445762751998208799limpbizkit
28597a51ffff130b192162f5a445762751998208799limpbizkit    final SingleUseScope replacementScope = new SingleUseScope();
28697a51ffff130b192162f5a445762751998208799limpbizkit
28797a51ffff130b192162f5a445762751998208799limpbizkit    Module original = new AbstractModule() {
28897a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
28997a51ffff130b192162f5a445762751998208799limpbizkit        bindScope(TestScopeAnnotation.class, scope);
29097a51ffff130b192162f5a445762751998208799limpbizkit        bind(Date.class).in(TestScopeAnnotation.class);
29197a51ffff130b192162f5a445762751998208799limpbizkit      }
29297a51ffff130b192162f5a445762751998208799limpbizkit    };
29397a51ffff130b192162f5a445762751998208799limpbizkit
29497a51ffff130b192162f5a445762751998208799limpbizkit    Module replacements = new AbstractModule() {
29597a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
29697a51ffff130b192162f5a445762751998208799limpbizkit        bindScope(TestScopeAnnotation.class, replacementScope);
29797a51ffff130b192162f5a445762751998208799limpbizkit      }
29897a51ffff130b192162f5a445762751998208799limpbizkit    };
29997a51ffff130b192162f5a445762751998208799limpbizkit
30097a51ffff130b192162f5a445762751998208799limpbizkit    Injector injector = createInjector(Modules.override(original).with(replacements));
30197a51ffff130b192162f5a445762751998208799limpbizkit    injector.getInstance(Date.class);
30297a51ffff130b192162f5a445762751998208799limpbizkit    assertTrue(replacementScope.used);
30397a51ffff130b192162f5a445762751998208799limpbizkit  }
30497a51ffff130b192162f5a445762751998208799limpbizkit
30597a51ffff130b192162f5a445762751998208799limpbizkit  public void testFailsIfOverridenScopeInstanceHasBeenUsed() {
30697a51ffff130b192162f5a445762751998208799limpbizkit    final Scope scope = new Scope() {
30797a51ffff130b192162f5a445762751998208799limpbizkit      public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
30897a51ffff130b192162f5a445762751998208799limpbizkit        return unscoped;
30997a51ffff130b192162f5a445762751998208799limpbizkit      }
31097a51ffff130b192162f5a445762751998208799limpbizkit
31197a51ffff130b192162f5a445762751998208799limpbizkit      @Override public String toString() {
31297a51ffff130b192162f5a445762751998208799limpbizkit        return "ORIGINAL SCOPE";
31397a51ffff130b192162f5a445762751998208799limpbizkit      }
31497a51ffff130b192162f5a445762751998208799limpbizkit    };
31597a51ffff130b192162f5a445762751998208799limpbizkit
3162e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    final Module original = new AbstractModule() {
31797a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
31897a51ffff130b192162f5a445762751998208799limpbizkit        bindScope(TestScopeAnnotation.class, scope);
31997a51ffff130b192162f5a445762751998208799limpbizkit        bind(Date.class).in(scope);
3202e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber        bind(String.class).in(scope);
3212e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      }
3222e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    };
3232e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    Module originalWrapper = new AbstractModule() {
3242e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @Override protected void configure() {
3252e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber        install(original);
32697a51ffff130b192162f5a445762751998208799limpbizkit      }
32797a51ffff130b192162f5a445762751998208799limpbizkit    };
32897a51ffff130b192162f5a445762751998208799limpbizkit
32997a51ffff130b192162f5a445762751998208799limpbizkit    Module replacements = new AbstractModule() {
33097a51ffff130b192162f5a445762751998208799limpbizkit      @Override protected void configure() {
33197a51ffff130b192162f5a445762751998208799limpbizkit        bindScope(TestScopeAnnotation.class, new SingleUseScope());
33297a51ffff130b192162f5a445762751998208799limpbizkit      }
33397a51ffff130b192162f5a445762751998208799limpbizkit    };
33497a51ffff130b192162f5a445762751998208799limpbizkit
33597a51ffff130b192162f5a445762751998208799limpbizkit    try {
3362e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      createInjector(Modules.override(originalWrapper).with(replacements));
33797a51ffff130b192162f5a445762751998208799limpbizkit      fail("Exception expected");
33897a51ffff130b192162f5a445762751998208799limpbizkit    } catch (CreationException e) {
339a6e0e787c546a1d5e82861b5c851ca09e3bbfd06limpbizkit      assertContains(e.getMessage(),
340a6e0e787c546a1d5e82861b5c851ca09e3bbfd06limpbizkit          "1) The scope for @TestScopeAnnotation is bound directly and cannot be overridden.",
3412e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          "original binding at " + original.getClass().getName() + ".configure(",
3422e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          asModuleChain(originalWrapper.getClass(), original.getClass()),
3432e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          "bound directly at " + original.getClass().getName() + ".configure(",
3442e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          asModuleChain(originalWrapper.getClass(), original.getClass()),
3452e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          "bound directly at " + original.getClass().getName() + ".configure(",
3462e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          asModuleChain(originalWrapper.getClass(), original.getClass()),
3472e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          "at ", replacements.getClass().getName() + ".configure(",
3482e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          asModuleChain(Modules.OverrideModule.class, replacements.getClass()));
34997a51ffff130b192162f5a445762751998208799limpbizkit    }
35097a51ffff130b192162f5a445762751998208799limpbizkit  }
35197a51ffff130b192162f5a445762751998208799limpbizkit
352edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit  public void testOverrideIsLazy() {
353edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit    final AtomicReference<String> value = new AtomicReference<String>("A");
354edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit    Module overridden = Modules.override(new AbstractModule() {
3552e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @Override protected void configure() {
356edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit        bind(String.class).annotatedWith(named("original")).toInstance(value.get());
357edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit      }
358edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit    }).with(new AbstractModule() {
3592e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @Override protected void configure() {
360edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit        bind(String.class).annotatedWith(named("override")).toInstance(value.get());
361edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit      }
362edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit    });
363edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit
364edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit    // the value.get() call should be deferred until Guice.createInjector
365edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit    value.set("B");
366edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit    Injector injector = Guice.createInjector(overridden);
367edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit    assertEquals("B", injector.getInstance(Key.get(String.class, named("original"))));
368edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit    assertEquals("B", injector.getInstance(Key.get(String.class, named("override"))));
369edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit  }
370edd8d64dbb0b5ff3b65973b362e400e7aea95ddblimpbizkit
371aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit  public void testOverridePrivateModuleOverPrivateModule() {
372aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    Module exposes5and6 = new AbstractModule() {
3732e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @Override protected void configure() {
374aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        install(new PrivateModule() {
3752e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          @Override protected void configure() {
376aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit            bind(Integer.class).toInstance(5);
377aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit            expose(Integer.class);
378aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
379aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit            bind(Character.class).toInstance('E');
380aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit          }
381aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        });
382aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
383aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        install(new PrivateModule() {
3842e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          @Override protected void configure() {
385aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit            bind(Long.class).toInstance(6L);
386aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit            expose(Long.class);
387aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
388aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit            bind(Character.class).toInstance('F');
389aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit          }
390aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        });
391aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit      }
392aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    };
393aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
394aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    AbstractModule exposes15 = new AbstractModule() {
3952e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @Override protected void configure() {
396aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        install(new PrivateModule() {
3972e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          @Override protected void configure() {
398aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit            bind(Integer.class).toInstance(15);
399aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit            expose(Integer.class);
400aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
401aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit            bind(Character.class).toInstance('G');
402aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit          }
403aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        });
404aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
405aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        install(new PrivateModule() {
4062e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          @Override protected void configure() {
407aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit            bind(Character.class).toInstance('H');
408aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit          }
409aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        });
410aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit      }
411aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    };
412aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
413aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    // override forwards
414aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    Injector injector = Guice.createInjector(Modules.override(exposes5and6).with(exposes15));
415aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    assertEquals(15, injector.getInstance(Integer.class).intValue());
416aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    assertEquals(6L, injector.getInstance(Long.class).longValue());
417aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
418aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    // and in reverse order
419aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    Injector reverse = Guice.createInjector(Modules.override(exposes15).with(exposes5and6));
420aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    assertEquals(5, reverse.getInstance(Integer.class).intValue());
421aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    assertEquals(6L, reverse.getInstance(Long.class).longValue());
422aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit  }
423aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
424aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit  public void testOverrideModuleAndPrivateModule() {
425aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    Module exposes5 = new PrivateModule() {
4262e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @Override protected void configure() {
427aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        bind(Integer.class).toInstance(5);
428aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        expose(Integer.class);
429aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit      }
430aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    };
431aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
432aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    Module binds15 = new AbstractModule() {
4332e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @Override protected void configure() {
434aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit        bind(Integer.class).toInstance(15);
435aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit      }
436aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    };
437aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
438aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    Injector injector = Guice.createInjector(Modules.override(exposes5).with(binds15));
439aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    assertEquals(15, injector.getInstance(Integer.class).intValue());
440aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
441aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    Injector reverse = Guice.createInjector(Modules.override(binds15).with(exposes5));
442aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit    assertEquals(5, reverse.getInstance(Integer.class).intValue());
443aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit  }
444aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
445ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit  public void testOverrideDeepExpose() {
446ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    final AtomicReference<Provider<Character>> charAProvider
447ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit        = new AtomicReference<Provider<Character>>();
448ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit
449ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    Module exposes5 = new PrivateModule() {
4502e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @Override protected void configure() {
451ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit        install(new PrivateModule() {
4522e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          @Override protected void configure() {
453ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit            bind(Integer.class).toInstance(5);
454ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit            expose(Integer.class);
455ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit            charAProvider.set(getProvider(Character.class));
456ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit            bind(Character.class).toInstance('A');
457ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit          }
458ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit        });
459ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit        expose(Integer.class);
460ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit      }
461ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    };
462ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit
463ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    Injector injector = Guice.createInjector(Modules.override(exposes5).with(EMPTY_MODULE));
464ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    assertEquals(5, injector.getInstance(Integer.class).intValue());
465ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    assertEquals('A', charAProvider.getAndSet(null).get().charValue());
466ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit
467ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    injector = Guice.createInjector(Modules.override(EMPTY_MODULE).with(exposes5));
468ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    assertEquals(5, injector.getInstance(Integer.class).intValue());
469ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    assertEquals('A', charAProvider.getAndSet(null).get().charValue());
470ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit
471ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    final AtomicReference<Provider<Character>> charBProvider
472ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit        = new AtomicReference<Provider<Character>>();
473ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit
474ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    Module binds15 = new AbstractModule() {
4752e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @Override protected void configure() {
476ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit        bind(Integer.class).toInstance(15);
477ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit
478ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit        install(new PrivateModule() {
4792e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber          @Override protected void configure() {
480ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit            charBProvider.set(getProvider(Character.class));
481ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit            bind(Character.class).toInstance('B');
482ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit          }
483ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit        });
484ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit      }
485ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    };
486ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit
487ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    injector = Guice.createInjector(Modules.override(binds15).with(exposes5));
488ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    assertEquals(5, injector.getInstance(Integer.class).intValue());
489ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    assertEquals('A', charAProvider.getAndSet(null).get().charValue());
490ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    assertEquals('B', charBProvider.getAndSet(null).get().charValue());
491ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit
492ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    injector = Guice.createInjector(Modules.override(exposes5).with(binds15));
493ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    assertEquals(15, injector.getInstance(Integer.class).intValue());
494ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    assertEquals('A', charAProvider.getAndSet(null).get().charValue());
495ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit    assertEquals('B', charBProvider.getAndSet(null).get().charValue());
496ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit  }
497ad8ed237dbae0d3723a6ed8cb1bcc83474444d4elimpbizkit
49897a51ffff130b192162f5a445762751998208799limpbizkit  @Retention(RUNTIME)
49997a51ffff130b192162f5a445762751998208799limpbizkit  @Target(TYPE)
50097a51ffff130b192162f5a445762751998208799limpbizkit  @ScopeAnnotation
50197a51ffff130b192162f5a445762751998208799limpbizkit  private static @interface TestScopeAnnotation {}
50297a51ffff130b192162f5a445762751998208799limpbizkit
50397a51ffff130b192162f5a445762751998208799limpbizkit  private static class SingleUseScope implements Scope {
50497a51ffff130b192162f5a445762751998208799limpbizkit    boolean used = false;
50597a51ffff130b192162f5a445762751998208799limpbizkit    public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
50697a51ffff130b192162f5a445762751998208799limpbizkit      assertFalse(used);
50797a51ffff130b192162f5a445762751998208799limpbizkit      used = true;
50897a51ffff130b192162f5a445762751998208799limpbizkit      return unscoped;
50997a51ffff130b192162f5a445762751998208799limpbizkit    }
51097a51ffff130b192162f5a445762751998208799limpbizkit  }
5112e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber
5122e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber  static class NewModule<T> extends AbstractModule {
5132e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    private final T bound;
5142e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    NewModule(T bound) {
5152e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      this.bound = bound;
5162e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    }
5172e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    @Override protected void configure() {
5182e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      @SuppressWarnings("unchecked")
5192e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      Class<T> type = (Class<T>)bound.getClass();
5202e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      bind(type).toInstance(bound);
5212e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    }
5222e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber  }
52397a51ffff130b192162f5a445762751998208799limpbizkit
5247e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit  private static <T> Module newModule(final T bound) {
5252e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    return new NewModule<T>(bound);
5267e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit  }
52719873c5c408e622cba43fe07614611062106057csberlin
52819873c5c408e622cba43fe07614611062106057csberlin  private static final String RESULT = "RESULT";
52919873c5c408e622cba43fe07614611062106057csberlin  private static final String PRIVATE_INPUT = "PRIVATE_INPUT";
53019873c5c408e622cba43fe07614611062106057csberlin  private static final String OVERRIDDEN_INPUT = "FOO";
53119873c5c408e622cba43fe07614611062106057csberlin  private static final String OVERRIDDEN_RESULT = "Size: 3";
53219873c5c408e622cba43fe07614611062106057csberlin  private static final Key<String> RESULT_KEY = Key.get(String.class, named(RESULT));
53319873c5c408e622cba43fe07614611062106057csberlin  private static final Key<String> INPUT_KEY = Key.get(String.class, named(PRIVATE_INPUT));
53419873c5c408e622cba43fe07614611062106057csberlin
53519873c5c408e622cba43fe07614611062106057csberlin  public void testExposedBindingOverride() throws Exception {
53619873c5c408e622cba43fe07614611062106057csberlin    Injector inj = Guice.createInjector(
53719873c5c408e622cba43fe07614611062106057csberlin        Modules.override(new ExampleModule()).with(
53819873c5c408e622cba43fe07614611062106057csberlin            new AbstractModule() {
53919873c5c408e622cba43fe07614611062106057csberlin              @Override protected void configure() {
54019873c5c408e622cba43fe07614611062106057csberlin                bind(RESULT_KEY).toInstance(OVERRIDDEN_RESULT);
54119873c5c408e622cba43fe07614611062106057csberlin              }
54219873c5c408e622cba43fe07614611062106057csberlin            }));
54319873c5c408e622cba43fe07614611062106057csberlin    assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT);
54419873c5c408e622cba43fe07614611062106057csberlin  }
54519873c5c408e622cba43fe07614611062106057csberlin
54619873c5c408e622cba43fe07614611062106057csberlin  public void testPrivateBindingOverride() throws Exception {
54719873c5c408e622cba43fe07614611062106057csberlin    Injector inj = Guice.createInjector(
54819873c5c408e622cba43fe07614611062106057csberlin        Modules.override(new ExampleModule()).with(
54919873c5c408e622cba43fe07614611062106057csberlin            new AbstractModule() {
55019873c5c408e622cba43fe07614611062106057csberlin              @Override protected void configure() {
55119873c5c408e622cba43fe07614611062106057csberlin                bind(INPUT_KEY).toInstance(OVERRIDDEN_INPUT);
55219873c5c408e622cba43fe07614611062106057csberlin              }
55319873c5c408e622cba43fe07614611062106057csberlin            }));
55419873c5c408e622cba43fe07614611062106057csberlin    assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT);
55519873c5c408e622cba43fe07614611062106057csberlin  }
55619873c5c408e622cba43fe07614611062106057csberlin
55719873c5c408e622cba43fe07614611062106057csberlin  public static class ExampleModule extends PrivateModule {
55819873c5c408e622cba43fe07614611062106057csberlin    @Provides @Exposed @Named(RESULT)
55919873c5c408e622cba43fe07614611062106057csberlin    public String provideResult(@Named(PRIVATE_INPUT) String input) {
56019873c5c408e622cba43fe07614611062106057csberlin      return "Size: " + input.length();
56119873c5c408e622cba43fe07614611062106057csberlin    }
56219873c5c408e622cba43fe07614611062106057csberlin
56319873c5c408e622cba43fe07614611062106057csberlin    @Provides @Named(PRIVATE_INPUT)
56419873c5c408e622cba43fe07614611062106057csberlin    public String provideInput() {
56519873c5c408e622cba43fe07614611062106057csberlin      return "Hello World";
56619873c5c408e622cba43fe07614611062106057csberlin    }
56719873c5c408e622cba43fe07614611062106057csberlin
56819873c5c408e622cba43fe07614611062106057csberlin    @Override protected void configure() {
56919873c5c408e622cba43fe07614611062106057csberlin    }
57019873c5c408e622cba43fe07614611062106057csberlin  }
5716d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin
5726d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin  public void testEqualsNotCalledByDefaultOnInstance() {
5736d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    final HashEqualsTester a = new HashEqualsTester();
5746d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    a.throwOnEquals = true;
5756d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    Guice.createInjector(Modules.override(new AbstractModule() {
5766d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      @Override
5776d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      protected void configure() {
5786d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin       bind(String.class);
5796d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin       bind(HashEqualsTester.class).toInstance(a);
5806d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      }
5816d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    }).with());
5826d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin  }
5836d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin
5846d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin  public void testEqualsNotCalledByDefaultOnProvider() {
5856d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    final HashEqualsTester a = new HashEqualsTester();
5866d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    a.throwOnEquals = true;
5876d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    Guice.createInjector(Modules.override(new AbstractModule() {
5886d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      @Override
5896d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      protected void configure() {
5906d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin       bind(String.class);
5916d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin       bind(Object.class).toProvider(a);
5926d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      }
5936d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    }).with());
5946d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin  }
5956d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin
5966d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin  public void testHashcodeNeverCalledOnInstance() {
5976d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    final HashEqualsTester a = new HashEqualsTester();
5986d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    a.throwOnHashcode = true;
5996d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    a.equality = "test";
6006d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin
6016d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    final HashEqualsTester b = new HashEqualsTester();
6026d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    b.throwOnHashcode = true;
6036d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    b.equality = "test";
6046d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    Guice.createInjector(Modules.override(new AbstractModule() {
6056d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      @Override
6066d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      protected void configure() {
6076d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin       bind(String.class);
6086d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin       bind(HashEqualsTester.class).toInstance(a);
6096d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin       bind(HashEqualsTester.class).toInstance(b);
6106d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      }
6116d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    }).with());
6126d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin  }
6136d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin
6146d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin  public void testHashcodeNeverCalledOnProviderInstance() {
6156d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    final HashEqualsTester a = new HashEqualsTester();
6166d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    a.throwOnHashcode = true;
6176d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    a.equality = "test";
6186d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin
6196d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    final HashEqualsTester b = new HashEqualsTester();
6206d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    b.throwOnHashcode = true;
6216d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    b.equality = "test";
6226d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    Guice.createInjector(Modules.override(new AbstractModule() {
6236d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      @Override
6246d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      protected void configure() {
6256d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin       bind(String.class);
6266d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin       bind(Object.class).toProvider(a);
6276d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin       bind(Object.class).toProvider(b);
6286d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      }
6296d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    }).with());
6306d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin  }
6316d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin
6326d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin  private static class HashEqualsTester implements Provider<Object> {
6336d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    private String equality;
6346d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    private boolean throwOnEquals;
6356d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    private boolean throwOnHashcode;
6366d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin
6376d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    @Override
6386d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    public boolean equals(Object obj) {
6396d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      if (throwOnEquals) {
6406d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin        throw new RuntimeException();
6416d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      } else if (obj instanceof HashEqualsTester) {
6426d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin        HashEqualsTester o = (HashEqualsTester)obj;
6436d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin        if(o.throwOnEquals) {
6446d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin          throw new RuntimeException();
6456d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin        }
6466d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin        if(equality == null && o.equality == null) {
6476d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin          return this == o;
6486d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin        } else {
6496d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin          return Objects.equal(equality, o.equality);
6506d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin        }
6516d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      } else {
6526d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin        return false;
6536d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      }
6546d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    }
6556d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin
6566d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    @Override
6576d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    public int hashCode() {
6586d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      if(throwOnHashcode) {
6596d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin        throw new RuntimeException();
6606d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      } else {
6616d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin        return super.hashCode();
6626d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      }
6636d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    }
6646d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin
6656d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    public Object get() {
6666d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin      return new Object();
6676d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin    }
6686d8ab0b649afffc5ae35eb832bfbaa3d95cc6c87sberlin  }
669ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin
670ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin  public void testCorrectStage() {
671ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin    final Stage stage = Stage.PRODUCTION;
672ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin    Module module = Modules.override(new AbstractModule() {
673ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin      @Override
674ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin      protected void configure() {
675ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin        if (currentStage() != Stage.PRODUCTION) {
676ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin          addError("Wronge stage in overridden module:" + currentStage());
677ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin        }
678ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin      }
679ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin    }).with(new AbstractModule() {
680ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin      @Override
681ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin      protected void configure() {
682ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin        if (currentStage() != Stage.PRODUCTION) {
683ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin          addError("Wronge stage in overriding module:" + currentStage());
684ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin        }
685ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin      }
686ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin    });
687ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin    Guice.createInjector(stage, module);
688ebe9f053ab2431f8f22f6d892cffadef4b10479cSam Berlin  }
68954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
69054da0e3ca924a5040e88a1c067f9f6760a14b20bsameb  public void testOverridesApplyOriginalScanners() {
69154da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    Injector injector =
69254da0e3ca924a5040e88a1c067f9f6760a14b20bsameb        Guice.createInjector(Modules.override(NamedMunger.module()).with(new AbstractModule() {
69354da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      @Override protected void configure() {}
69454da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      @TestProvides @Named("test") String provideString() { return "foo"; }
69554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    }));
69654da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
69754da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    assertNull(injector.getExistingBinding(Key.get(String.class, named("test"))));
69854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    Binding<String> binding = injector.getBinding(Key.get(String.class, named("test-munged")));
69954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    assertEquals("foo", binding.getProvider().get());
70054da0e3ca924a5040e88a1c067f9f6760a14b20bsameb  }
70154da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
70254da0e3ca924a5040e88a1c067f9f6760a14b20bsameb  @Documented @Target(METHOD) @Retention(RUNTIME)
70354da0e3ca924a5040e88a1c067f9f6760a14b20bsameb  private @interface TestProvides {}
70454da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
70554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb  private static class NamedMunger extends ModuleAnnotatedMethodScanner {
70654da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    static Module module() {
70754da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      return new AbstractModule() {
70854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb        @Override protected void configure() {
70954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb          binder().scanModulesForAnnotatedMethods(new NamedMunger());
71054da0e3ca924a5040e88a1c067f9f6760a14b20bsameb        }
71154da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      };
71254da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    }
71354da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
71454da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    @Override
71554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    public String toString() {
71654da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      return "NamedMunger";
71754da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    }
71854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
71954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    @Override
72054da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    public Set<? extends Class<? extends Annotation>> annotationClasses() {
72154da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      return ImmutableSet.of(TestProvides.class);
72254da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    }
72354da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
72454da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    @Override
72554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    public <T> Key<T> prepareMethod(Binder binder, Annotation annotation, Key<T> key,
72654da0e3ca924a5040e88a1c067f9f6760a14b20bsameb        InjectionPoint injectionPoint) {
72754da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      return Key.get(key.getTypeLiteral(),
72854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb          Names.named(((Named) key.getAnnotation()).value() + "-munged"));
72954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    }
73054da0e3ca924a5040e88a1c067f9f6760a14b20bsameb  }
7315a72c099f791eeeba8dde89e27f84bb952615aa4limpbizkit}
732