/**
 * Copyright (C) 2011 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.inject;

import static com.google.common.collect.ImmutableList.of;
import static com.google.inject.Asserts.assertContains;
import static com.google.inject.name.Names.named;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.matcher.Matcher;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Named;
import com.google.inject.spi.DependencyAndSource;
import com.google.inject.spi.InstanceBinding;
import com.google.inject.spi.ProvisionListener;
import com.google.inject.util.Providers;

import junit.framework.TestCase;

import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Tests for {@link Binder#bindListener(Matcher, ProvisionListener...)}
 * 
 * @author sameb@google.com (Sam Berlin)
 */
// TODO(sameb): Add some tests for private modules & child injectors.
public class ProvisionListenerTest extends TestCase {

  public void testExceptionInListenerBeforeProvisioning() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new FailBeforeProvision());
      }
    });
    try {
      injector.getInstance(Foo.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error notifying ProvisionListener " + FailBeforeProvision.class.getName()
          + " of " + Foo.class.getName(),
          "Reason: java.lang.RuntimeException: boo",
          "while locating " + Foo.class.getName());
      assertEquals("boo", pe.getCause().getMessage());
    }
  }
  
  public void testExceptionInListenerAfterProvisioning() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new FailAfterProvision());
      }
    });
    try {
      injector.getInstance(Foo.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error notifying ProvisionListener " + FailAfterProvision.class.getName()
          + " of " + Foo.class.getName(),
          "Reason: java.lang.RuntimeException: boo",
          "while locating " + Foo.class.getName());
      assertEquals("boo", pe.getCause().getMessage());
    }
  }
  
  public void testExceptionInProvisionExplicitlyCalled() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new JustProvision());
      }
    });
    try {
      injector.getInstance(FooBomb.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
          " at " + FooBomb.class.getName(),
          " while locating " + FooBomb.class.getName());
      assertEquals("Retry, Abort, Fail", pe.getCause().getMessage());
    }
  }
  
  public void testExceptionInProvisionAutomaticallyCalled() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new NoProvision());
      }
    });
    try {
      injector.getInstance(FooBomb.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
          " at " + FooBomb.class.getName(),
          " while locating " + FooBomb.class.getName());
      assertEquals("Retry, Abort, Fail", pe.getCause().getMessage());
    }
  }
  
  public void testExceptionInFieldProvision() throws Exception {
    final CountAndCaptureExceptionListener listener = new CountAndCaptureExceptionListener();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        bindListener(new AbstractMatcher<Binding<?>>() {
          @Override public boolean matches(Binding<?> binding) {
            return binding.getKey().getRawType().equals(DependsOnFooBombInField.class);
          }
        }, listener);
      }
    });
    assertEquals(0, listener.beforeProvision);
    String expectedMsg = null;
    try {
      injector.getInstance(DependsOnFooBombInField.class);
      fail();
    } catch (ProvisionException expected) {
      assertEquals(1, expected.getErrorMessages().size());
      expectedMsg = expected.getMessage();
      assertContains(listener.capture.get().getMessage(),
          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
          " at " + FooBomb.class.getName(),
          " while locating " + FooBomb.class.getName(),
          " while locating " + DependsOnFooBombInField.class.getName());
    }
    assertEquals(1, listener.beforeProvision);
    assertEquals(expectedMsg, listener.capture.get().getMessage());
    assertEquals(0, listener.afterProvision);
  }
  
  public void testExceptionInCxtorProvision() throws Exception {
    final CountAndCaptureExceptionListener listener = new CountAndCaptureExceptionListener();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        bindListener(new AbstractMatcher<Binding<?>>() {
          @Override public boolean matches(Binding<?> binding) {
            return binding.getKey().getRawType().equals(DependsOnFooBombInCxtor.class);
          }
        }, listener);
      }
    });
    assertEquals(0, listener.beforeProvision);
    String expectedMsg = null;
    try {
      injector.getInstance(DependsOnFooBombInCxtor.class);
      fail();
    } catch (ProvisionException expected) {
      assertEquals(1, expected.getErrorMessages().size());
      expectedMsg = expected.getMessage();
      assertContains(listener.capture.get().getMessage(),
          "1) Error injecting constructor, java.lang.RuntimeException: Retry, Abort, Fail",
          " at " + FooBomb.class.getName(),
          " while locating " + FooBomb.class.getName(),
          " while locating " + DependsOnFooBombInCxtor.class.getName());
    }
    assertEquals(1, listener.beforeProvision);
    assertEquals(expectedMsg, listener.capture.get().getMessage());
    assertEquals(0, listener.afterProvision);
  }

  public void testListenerCallsProvisionTwice() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new ProvisionTwice());
      }
    });
    try {
      injector.getInstance(Foo.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error notifying ProvisionListener " + ProvisionTwice.class.getName()
          + " of " + Foo.class.getName(),
          "Reason: java.lang.IllegalStateException: Already provisioned in this listener.",
          "while locating " + Foo.class.getName());
      assertEquals("Already provisioned in this listener.", pe.getCause().getMessage());  
    }
  }
  
  public void testCachedInScopePreventsProvisionNotify() {
    final Counter count1 = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), count1);
        bind(Foo.class).in(Scopes.SINGLETON);
      }
    });
    Foo foo = injector.getInstance(Foo.class);
    assertNotNull(foo);
    assertEquals(1, count1.count);
    
    // not notified the second time because nothing is provisioned
    // (it's cached in the scope)
    count1.count = 0;
    assertSame(foo, injector.getInstance(Foo.class));
    assertEquals(0, count1.count);
  }
  
  public void testCombineAllBindListenerCalls() {
    final Counter count1 = new Counter();
    final Counter count2 = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), count1);
        bindListener(Matchers.any(), count2);
      }
    });
    assertNotNull(injector.getInstance(Foo.class));
    assertEquals(1, count1.count);
    assertEquals(1, count2.count);
  }
  
  public void testNotifyEarlyListenersIfFailBeforeProvision() {
    final Counter count1 = new Counter();
    final Counter count2 = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), count1, new FailBeforeProvision(), count2);
      }
    });
    try {
      injector.getInstance(Foo.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error notifying ProvisionListener " + FailBeforeProvision.class.getName()
          + " of " + Foo.class.getName(),
          "Reason: java.lang.RuntimeException: boo",
          "while locating " + Foo.class.getName());
      assertEquals("boo", pe.getCause().getMessage());
      
      assertEquals(1, count1.count);
      assertEquals(0, count2.count);
    }
  }
  
  public void testNotifyLaterListenersIfFailAfterProvision() {
    final Counter count1 = new Counter();
    final Counter count2 = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), count1, new FailAfterProvision(), count2);
      }
    });
    try {
      injector.getInstance(Foo.class);
      fail();
    } catch(ProvisionException pe) {
      assertEquals(1, pe.getErrorMessages().size());
      assertContains(pe.getMessage(),
          "1) Error notifying ProvisionListener " + FailAfterProvision.class.getName()
          + " of " + Foo.class.getName(),
          "Reason: java.lang.RuntimeException: boo",
          "while locating " + Foo.class.getName());
      assertEquals("boo", pe.getCause().getMessage());
      
      assertEquals(1, count1.count);
      assertEquals(1, count2.count);
    }
  }
  
  public void testNotifiedKeysOfAllBindTypes() {
    final Capturer capturer = new Capturer();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), capturer);
        bind(Foo.class).annotatedWith(named("pk")).toProvider(FooP.class);
        try {
          bind(Foo.class).annotatedWith(named("cxtr")).toConstructor(Foo.class.getDeclaredConstructor());
        } catch (Exception ex) {
          throw new RuntimeException(ex);
        }
        bind(LinkedFoo.class).to(Foo.class);
        bind(Interface.class).toInstance(new Implementation());
        bindConstant().annotatedWith(named("constant")).to("MyConstant");
      }
      
      @Provides @Named("pi") Foo provideFooBar() {
        return new Foo();
      }
    });
    
    // toInstance & constant bindings are notified in random order, at the very beginning.
    assertEquals(
        ImmutableSet.of(Key.get(Interface.class), Key.get(String.class, named("constant"))),
        capturer.getAsSetAndClear());
    
    // simple binding
    assertNotNull(injector.getInstance(Foo.class));
    assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());
    
    // provider key binding -- notifies about provider & the object, always
    assertNotNull(injector.getInstance(Key.get(Foo.class, named("pk"))));
    assertEquals(of(Key.get(FooP.class), Key.get(Foo.class, named("pk"))), capturer.getAndClear());
    assertNotNull(injector.getInstance(Key.get(Foo.class, named("pk"))));
    assertEquals(of(Key.get(FooP.class), Key.get(Foo.class, named("pk"))), capturer.getAndClear());
    
    // JIT provider key binding -- notifies about provider & the object, always
    assertNotNull(injector.getInstance(JitFoo2.class));
    assertEquals(of(Key.get(JitFoo2P.class), Key.get(JitFoo2.class)), capturer.getAndClear());
    assertNotNull(injector.getInstance(JitFoo2.class));
    assertEquals(of(Key.get(JitFoo2P.class), Key.get(JitFoo2.class)), capturer.getAndClear());
    
    // provider instance binding -- just the object (not the provider)
    assertNotNull(injector.getInstance(Key.get(Foo.class, named("pi"))));
    assertEquals(of(Key.get(Foo.class, named("pi"))), capturer.getAndClear());
    
    // toConstructor binding
    assertNotNull(injector.getInstance(Key.get(Foo.class, named("cxtr"))));
    assertEquals(of(Key.get(Foo.class, named("cxtr"))), capturer.getAndClear());
    
    // linked binding -- notifies about the target (that's what's provisioned), not the link
    assertNotNull(injector.getInstance(LinkedFoo.class));
    assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());

    // JIT linked binding -- notifies about the target (that's what's provisioned), not the link
    assertNotNull(injector.getInstance(JitFoo.class));
    assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());
  }
  
  public void testSingletonMatcher() {
    final Counter counter = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(new AbstractMatcher<Binding<?>>() {
          @Override
          public boolean matches(Binding<?> t) {
            return Scopes.isSingleton(t);
          }
        }, counter);
      }
    });
    assertEquals(0, counter.count);
    // no increment for getting Many.
    injector.getInstance(Many.class);
    assertEquals(0, counter.count);
    // but an increment for getting Sole, since it's a singleton.
    injector.getInstance(Sole.class);
    assertEquals(1, counter.count);
  }
  
  public void testCallingBindingDotGetProviderDotGet() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new ProvisionListener() {
          @Override
          public <T> void onProvision(ProvisionInvocation<T> provision) {
            provision.getBinding().getProvider().get(); // AGH!
          }
        });
      }
    });
    
    try {
      injector.getInstance(Sole.class);
      fail();
    } catch(ProvisionException expected) {
      // We don't really care what kind of error you get, we only care you get an error.
    }
    
    try {
      injector.getInstance(Many.class);
      fail();
    } catch(ProvisionException expected) {
      // We don't really care what kind of error you get, we only care you get an error.
    }
  }
  
  interface Interface {}
  class Implementation implements Interface {}
  
  @Singleton static class Sole {}
  static class Many {}
  
  @ImplementedBy(Foo.class) static interface JitFoo {}  
  @ProvidedBy(JitFoo2P.class) static class JitFoo2 {}  
  static interface LinkedFoo {}
  static class Foo implements JitFoo, LinkedFoo {}
  static class FooP implements Provider<Foo> {
    public Foo get() {
      return new Foo();
    }
  }
  static class JitFoo2P implements Provider<JitFoo2> {
    public JitFoo2 get() {
      return new JitFoo2();
    }
  }
  
  static class FooBomb {
    FooBomb() {
      throw new RuntimeException("Retry, Abort, Fail");
    }
  }
  
  static class DependsOnFooBombInField {
    @Inject FooBomb fooBomb;
  }
  
  static class DependsOnFooBombInCxtor {
    @Inject DependsOnFooBombInCxtor(FooBomb fooBomb) {}
  }
  
  private static class Counter implements ProvisionListener {
    int count = 0;
    public <T> void onProvision(ProvisionInvocation<T> provision) {
      count++;
    }
  }
  
  private static class CountAndCaptureExceptionListener implements ProvisionListener {
    int beforeProvision = 0;
    int afterProvision = 0;
    AtomicReference<RuntimeException> capture = new AtomicReference<RuntimeException>();
    public <T> void onProvision(ProvisionInvocation<T> provision) {
      beforeProvision++;
      try {
        provision.provision();
      } catch (RuntimeException re) {
        capture.set(re);
        throw re;
      }
      afterProvision++;
    }
  }
  
  private static class Capturer implements ProvisionListener {
    List<Key> keys = Lists.newArrayList(); 
    public <T> void onProvision(ProvisionInvocation<T> provision) {
      keys.add(provision.getBinding().getKey());
      T provisioned = provision.provision();
      // InstanceBindings are the only kind of binding where the key can
      // be an instanceof the provisioned, because it isn't linked to any
      // direct implementation.  I guess maybe it'd also be possible
      // with a toConstructor binding... but we don't use that in our tests.
      if (provision.getBinding() instanceof InstanceBinding) {
        Class<? super T> expected = provision.getBinding().getKey().getRawType();
        assertTrue("expected instanceof: " + expected + ", but was: " + provisioned,
            expected.isInstance(provisioned));
      } else {
        assertEquals(provision.getBinding().getKey().getRawType(), provisioned.getClass());
      }
    }
    
    Set<Key> getAsSetAndClear() {
      Set<Key> copy = ImmutableSet.copyOf(keys);
      keys.clear();
      return copy;
    }
    
    List<Key> getAndClear() {
      List<Key> copy = ImmutableList.copyOf(keys);
      keys.clear();
      return copy;
    }
  }

  private static class FailBeforeProvision implements ProvisionListener {
    public <T> void onProvision(ProvisionInvocation<T> provision) {
      throw new RuntimeException("boo");
    }
  }  
  private static class FailAfterProvision implements ProvisionListener {
    public <T> void onProvision(ProvisionInvocation<T> provision) {
      provision.provision();
      throw new RuntimeException("boo");
    }
  }  
  private static class JustProvision implements ProvisionListener {
    public <T> void onProvision(ProvisionInvocation<T> provision) {
      provision.provision();
    }
  }  
  private static class NoProvision implements ProvisionListener {
    public <T> void onProvision(ProvisionInvocation<T> provision) {
    }
  }
  private static class ProvisionTwice implements ProvisionListener {
    public <T> void onProvision(ProvisionInvocation<T> provision) {
      provision.provision();
      provision.provision();
    }
  }
  
  private static class ChainAsserter implements ProvisionListener {
    private final List<Class<?>> provisionList;
    private final List<Class<?>> expected;
    
    public ChainAsserter(List<Class<?>> provisionList, Iterable<Class<?>> expected) {
      this.provisionList = provisionList;
      this.expected = ImmutableList.copyOf(expected);
    }
    
    public <T> void onProvision(ProvisionInvocation<T> provision) {
      List<Class<?>> actual = Lists.newArrayList();
      for (DependencyAndSource dep : provision.getDependencyChain()) {
        actual.add(dep.getDependency().getKey().getRawType());
      }
      assertEquals(expected, actual);
      provisionList.add(provision.getBinding().getKey().getRawType());
    }
  }
  
  private static Matcher<Binding<?>> keyMatcher(final Class<?> clazz) {
    return new AbstractMatcher<Binding<?>>() {
      @Override
      public boolean matches(Binding<?> t) {
        return t.getKey().equals(Key.get(clazz));
      }
    };
  }
  
  @SuppressWarnings("unchecked")
  public void testDependencyChain() {
    final List<Class<?>> pList = Lists.newArrayList();
    final List<Class<?>> totalList = Lists.newArrayList();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Instance.class).toInstance(new Instance());
        bind(B.class).to(BImpl.class);
        bind(D.class).toProvider(DP.class);
        
        bindListener(Matchers.any(), new ProvisionListener() {
          public <T> void onProvision(ProvisionInvocation<T> provision) {
            totalList.add(provision.getBinding().getKey().getRawType());
          }
        });
        
        // Build up a list of asserters for our dependency chains.
        ImmutableList.Builder<Class<?>> chain = ImmutableList.builder();
        chain.add(Instance.class);
        bindListener(keyMatcher(Instance.class), new ChainAsserter(pList, chain.build()));
        
        chain.add(A.class);
        bindListener(keyMatcher(A.class), new ChainAsserter(pList, chain.build()));
        
        chain.add(B.class).add(BImpl.class);
        bindListener(keyMatcher(BImpl.class), new ChainAsserter(pList, chain.build()));
        
        chain.add(C.class);
        bindListener(keyMatcher(C.class), new ChainAsserter(pList, chain.build()));
        
        // the chain has D before DP even though DP is provisioned & notified first
        // because we do DP because of D, and need DP to provision D.
        chain.add(D.class).add(DP.class);
        bindListener(keyMatcher(D.class), new ChainAsserter(pList, chain.build()));
        bindListener(keyMatcher(DP.class), new ChainAsserter(pList, chain.build()));
        
        chain.add(E.class);
        bindListener(keyMatcher(E.class), new ChainAsserter(pList, chain.build()));
        
        chain.add(F.class);
        bindListener(keyMatcher(F.class), new ChainAsserter(pList, chain.build()));
      }
      @Provides C c(D d) {
        return new C() {};
      }
    });
    Instance instance = injector.getInstance(Instance.class);
    // make sure we're checking all of the chain asserters..
    assertEquals(
        of(Instance.class, A.class, BImpl.class, C.class, DP.class, D.class, E.class, F.class),
        pList);
    // and make sure that nothing else was notified that we didn't expect.
    assertEquals(totalList, pList);
  }
  
  public void testModuleRequestInjection() {
    final AtomicBoolean notified = new AtomicBoolean();    
    Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        requestInjection(new Object() {
          @Inject Foo foo;
        });
        bindListener(Matchers.any(),
            new SpecialChecker(Foo.class, getClass().getName() + ".configure(", notified));
      }
    });
    assertTrue(notified.get());
  }
  
  public void testToProviderInstance() {
    final AtomicBoolean notified = new AtomicBoolean();    
    Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Object.class).toProvider(new Provider<Object>() {
          @Inject Foo foo;
          public Object get() {
            return null;
          }
        });
        bindListener(Matchers.any(),
            new SpecialChecker(Foo.class, getClass().getName() + ".configure(", notified));
      }
    });
    assertTrue(notified.get());
  }
  
  public void testInjectorInjectMembers() {
    final Object object = new Object() {
      @Inject Foo foo;
    };
    final AtomicBoolean notified = new AtomicBoolean();    
    Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(),
            new SpecialChecker(Foo.class, object.getClass().getName(), notified));
      }
    }).injectMembers(object);
    assertTrue(notified.get());
  }
  
  private static class SpecialChecker implements ProvisionListener {
    private final Class<?> notifyType;
    private final String firstSource;
    private final AtomicBoolean notified;
    
    public SpecialChecker(Class<?> notifyType, String firstSource, AtomicBoolean notified) {
      this.notifyType = notifyType;
      this.firstSource = firstSource;
      this.notified = notified;
    }
    
    public <T> void onProvision(ProvisionInvocation<T> provision) {
      notified.set(true);
      assertEquals(notifyType, provision.getBinding().getKey().getRawType());            
      assertEquals(2, provision.getDependencyChain().size());
      
      assertNull(provision.getDependencyChain().get(0).getDependency());
      assertContains(provision.getDependencyChain().get(0).getBindingSource(), firstSource);
      
      assertEquals(notifyType,
          provision.getDependencyChain().get(1).getDependency().getKey().getRawType());
      assertContains(provision.getDependencyChain().get(1).getBindingSource(),
          notifyType.getName() + ".class(");
    }
  }
  
  private static class Instance {
    @Inject A a;
  }
  private static class A {
    @Inject A(B b) {}
  }
  private interface B {}
  private static class BImpl implements B {
    @Inject void inject(C c) {}
  }
  private interface C {}
  private interface D {}
  private static class DP implements Provider<D> {
    @Inject Provider<E> ep;
    public D get() {
      ep.get();
      return new D() {};
    }
  }
  private static class E {
    @SuppressWarnings("unused")
    @Inject F f;
  }
  private static class F {
  }

  public void testBindToInjectorWithListeningGivesSaneException() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          bindListener(Matchers.any(), new Counter());
          bind(Injector.class).toProvider(Providers.<Injector>of(null));
        }
      });
      fail();
    } catch (CreationException ce) {
      assertContains(
          ce.getMessage(), "Binding to core guice framework type is not allowed: Injector.");
    }
  }

  public void testProvisionIsNotifiedAfterContextsClear() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), new ProvisionListener() {
          @Override
          public <T> void onProvision(ProvisionInvocation<T> provision) {
            Object provisioned = provision.provision();
            if (provisioned instanceof X) {
              ((X)provisioned).init();
            } else if (provisioned instanceof Y) {
              X.createY = false;
              ((Y)provisioned).init();
            }
          }
        });
      }
    });

    X.createY = true;
    X x = injector.getInstance(X.class);
    assertNotSame(x, x.y.x);
    assertFalse("x.ID: " + x.ID + ", x.y.x.iD: " + x.y.x.ID, x.ID == x.y.x.ID);
  }

  private static class X {
    final static AtomicInteger COUNTER = new AtomicInteger();
    static boolean createY;

    final int ID = COUNTER.getAndIncrement();
    final Provider<Y> yProvider;
    Y y;

    @Inject X(Provider<Y> yProvider) {
      this.yProvider = yProvider;
    }

    void init() {
      if (createY) {
        this.y = yProvider.get();
      }
    }
  }

  private static class Y {
    final Provider<X> xProvider;
    X x;

    @Inject Y(Provider<X> xProvider) {
      this.xProvider = xProvider;
    }

    void init() {
      this.x = xProvider.get();
    }
  }
  
  public void testDeDuplicateProvisionListeners() {
    final Counter counter = new Counter();
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindListener(Matchers.any(), counter);
        bindListener(Matchers.any(), counter);
      }
    });
    injector.getInstance(Many.class);
    assertEquals("ProvisionListener not de-duplicated", 1, counter.count);
  }
}
