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

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.AbstractModule;
import com.google.inject.Asserts;
import com.google.inject.BindingAnnotation;
import com.google.inject.CreationException;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.OutOfScopeException;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import com.google.inject.Scope;
import com.google.inject.ScopeAnnotation;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.util.Classes;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.Message;
import com.google.inject.throwingproviders.ThrowingProviderBinder.Result;

import junit.framework.TestCase;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.net.BindException;
import java.rmi.AccessException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TooManyListenersException;

/**
 * @author jmourits@google.com (Jerome Mourits)
 * @author jessewilson@google.com (Jesse Wilson)
 * @author sameb@google.com (Sam Berlin)
 */
public class CheckedProviderTest extends TestCase {
  @Target(METHOD) @Retention(RUNTIME) @BindingAnnotation
  @interface NotExceptionScoping { };
  
  private static final Function<Dependency<?>, Key<?>> DEPENDENCY_TO_KEY =
      new Function<Dependency<?>, Key<?>>() {
        public Key<?> apply(Dependency<?> from) {
          return from.getKey();
        }
      };

  private final TypeLiteral<RemoteProvider<Foo>> remoteProviderOfFoo
      = new TypeLiteral<RemoteProvider<Foo>>() { };
  private final MockRemoteProvider<Foo> mockRemoteProvider = new MockRemoteProvider<Foo>();
  private final TestScope testScope = new TestScope();
  
  private Injector bindInjector;  
  private Injector providesInjector;
  private Injector cxtorInjector;
  
  @Override
  protected void setUp() throws Exception {
    MockFoo.nextToThrow = null;
    MockFoo.nextToReturn = null;
    AnotherMockFoo.nextToThrow = null;
    AnotherMockFoo.nextToReturn = null;
    
    bindInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, Foo.class)
            .to(mockRemoteProvider)
            .in(testScope);

        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, Foo.class)
            .annotatedWith(NotExceptionScoping.class)
            .scopeExceptions(false)
            .to(mockRemoteProvider)
            .in(testScope);

      }
    });  
    
    providesInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
       install(ThrowingProviderBinder.forModule(this));
       bindScope(TestScope.Scoped.class, testScope);
      }
      
      @SuppressWarnings("unused")
      @CheckedProvides(RemoteProvider.class)
      @TestScope.Scoped
      Foo throwOrGet() throws RemoteException, BindException {
        return mockRemoteProvider.get();
      }

      @SuppressWarnings("unused")
      @CheckedProvides(value = RemoteProvider.class, scopeExceptions = false)
      @NotExceptionScoping
      @TestScope.Scoped
      Foo notExceptionScopingThrowOrGet() throws RemoteException, BindException {
        return mockRemoteProvider.get();
      }    
      
    });
    
    cxtorInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        ThrowingProviderBinder.create(binder())
          .bind(RemoteProvider.class, Foo.class)
          .providing(MockFoo.class)
          .in(testScope);

        ThrowingProviderBinder.create(binder())
          .bind(RemoteProvider.class, Foo.class)
          .annotatedWith(NotExceptionScoping.class)
          .scopeExceptions(false)
          .providing(MockFoo.class)
          .in(testScope);
        
      }
    });
  }

  public void testExceptionsThrown_Bind() throws Exception {
    tExceptionsThrown(bindInjector);
  }
  
  public void testExceptionsThrown_Provides() throws Exception {
    tExceptionsThrown(providesInjector);
  }
  
  public void testExceptionsThrown_Cxtor() throws Exception {
    tExceptionsThrown(cxtorInjector);
  }
  
  private void tExceptionsThrown(Injector injector) throws Exception {
    RemoteProvider<Foo> remoteProvider = 
      injector.getInstance(Key.get(remoteProviderOfFoo));

    mockRemoteProvider.throwOnNextGet(new BindException("kaboom!"));
    MockFoo.nextToThrow = new BindException("kaboom!");
    try {
      remoteProvider.get();
      fail();
    } catch (BindException expected) {
      assertEquals("kaboom!", expected.getMessage());
    }
  }

  public void testValuesScoped_Bind() throws Exception  {
    tValuesScoped(bindInjector, null);
  }
  
  public void testValuesScoped_Provides() throws Exception  {
    tValuesScoped(providesInjector, null);
  }
  
  public void testValuesScopedWhenNotExceptionScoping_Bind() throws Exception  {
    tValuesScoped(bindInjector, NotExceptionScoping.class);
  }
  
  public void testValuesScopedWhenNotExceptionScoping_Provides() throws Exception  {
    tValuesScoped(providesInjector, NotExceptionScoping.class);
  }

  private void tValuesScoped(Injector injector, 
      Class<? extends Annotation> annotation) throws Exception {
    Key<RemoteProvider<Foo>> key = annotation != null ? 
        Key.get(remoteProviderOfFoo, annotation) :
        Key.get(remoteProviderOfFoo);
    RemoteProvider<Foo> remoteProvider = injector.getInstance(key);
    
    mockRemoteProvider.setNextToReturn(new SimpleFoo("A"));
    assertEquals("A", remoteProvider.get().s());

    mockRemoteProvider.setNextToReturn(new SimpleFoo("B"));
    assertEquals("A", remoteProvider.get().s());

    testScope.beginNewScope();
    assertEquals("B", remoteProvider.get().s());
  }
  
  public void testValuesScoped_Cxtor() throws Exception {
    RemoteProvider<Foo> remoteProvider = 
        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));

    Foo retrieved = remoteProvider.get();
    assertSame(retrieved, remoteProvider.get()); // same, not in new scope.
    
    testScope.beginNewScope();
    assertNotSame(retrieved, remoteProvider.get()); // different, new scope.
  }

  public void testExceptionsScoped_Bind() throws Exception {
    tExceptionsScoped(bindInjector);
  }
  
  public void testExceptionsScoped_Provides() throws Exception {
    tExceptionsScoped(providesInjector);
  }
  
  public void testExceptionScopes_Cxtor() throws Exception {
    tExceptionsScoped(cxtorInjector);
  }
  
  private void tExceptionsScoped(Injector injector) throws Exception {
    RemoteProvider<Foo> remoteProvider = 
        injector.getInstance(Key.get(remoteProviderOfFoo));

    mockRemoteProvider.throwOnNextGet(new RemoteException("A"));
    MockFoo.nextToThrow = new RemoteException("A");
    try {
      remoteProvider.get();
      fail();
    } catch (RemoteException expected) {
      assertEquals("A", expected.getMessage());
    }
    
    mockRemoteProvider.throwOnNextGet(new RemoteException("B"));
    MockFoo.nextToThrow = new RemoteException("B");
    try {
      remoteProvider.get();
      fail();
    } catch (RemoteException expected) {
      assertEquals("A", expected.getMessage());
    }
  }
  
  public void testExceptionsNotScopedWhenNotExceptionScoping_Bind() throws Exception {
    tExceptionsNotScopedWhenNotExceptionScoping(bindInjector);
  }
  
  public void testExceptionsNotScopedWhenNotExceptionScoping_Provides() throws Exception {
    tExceptionsNotScopedWhenNotExceptionScoping(providesInjector);
  }
  
  public void testExceptionNotScopedWhenNotExceptionScoping_Cxtor() throws Exception {
    tExceptionsNotScopedWhenNotExceptionScoping(cxtorInjector);
  }
  
  private void tExceptionsNotScopedWhenNotExceptionScoping(Injector injector) throws Exception {
    RemoteProvider<Foo> remoteProvider = 
        injector.getInstance(Key.get(remoteProviderOfFoo, NotExceptionScoping.class));

    mockRemoteProvider.throwOnNextGet(new RemoteException("A"));
    MockFoo.nextToThrow = new RemoteException("A");
    try {
      remoteProvider.get();
      fail();
    } catch (RemoteException expected) {
      assertEquals("A", expected.getMessage());
    }
    
    mockRemoteProvider.throwOnNextGet(new RemoteException("B"));
    MockFoo.nextToThrow = new RemoteException("B");
    try {
      remoteProvider.get();
      fail();
    } catch (RemoteException expected) {
      assertEquals("B", expected.getMessage());
    }
  }
  
  public void testAnnotations_Bind() throws Exception {
    final MockRemoteProvider<Foo> mockRemoteProviderA = new MockRemoteProvider<Foo>();
    final MockRemoteProvider<Foo> mockRemoteProviderB = new MockRemoteProvider<Foo>();
    bindInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, Foo.class)
            .annotatedWith(Names.named("a"))
            .to(mockRemoteProviderA);

        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, Foo.class)
            .to(mockRemoteProviderB);
      }
    });
    tAnnotations(bindInjector, mockRemoteProviderA, mockRemoteProviderB);
  }
  
  public void testAnnotations_Provides() throws Exception {
    final MockRemoteProvider<Foo> mockRemoteProviderA = new MockRemoteProvider<Foo>();
    final MockRemoteProvider<Foo> mockRemoteProviderB = new MockRemoteProvider<Foo>();
    providesInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        install(ThrowingProviderBinder.forModule(this));
       }
       
       @SuppressWarnings("unused")
       @CheckedProvides(RemoteProvider.class)
       @Named("a")
       Foo throwOrGet() throws RemoteException, BindException {
         return mockRemoteProviderA.get();
       }
       
       @SuppressWarnings("unused")
       @CheckedProvides(RemoteProvider.class)
       Foo throwOrGet2() throws RemoteException, BindException {
         return mockRemoteProviderB.get();
       }
    });
    tAnnotations(providesInjector, mockRemoteProviderA, mockRemoteProviderB);
  }
  
  private void tAnnotations(Injector injector, MockRemoteProvider<Foo> mockA,
      MockRemoteProvider<Foo> mockB) throws Exception {
    mockA.setNextToReturn(new SimpleFoo("A"));
    mockB.setNextToReturn(new SimpleFoo("B"));
    assertEquals("A", 
        injector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s());

    assertEquals("B", 
        injector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
  }
  
  public void testAnnotations_Cxtor() throws Exception {
    cxtorInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, Foo.class)
            .annotatedWith(Names.named("a"))
            .providing(MockFoo.class);

        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, Foo.class)
            .providing(AnotherMockFoo.class);
      }
    });
    MockFoo.nextToReturn = "A";
    AnotherMockFoo.nextToReturn = "B";
    assertEquals("A", 
        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s());

    assertEquals("B", 
        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
  }
  
  public void testUndeclaredExceptions_Bind() throws Exception {
    tUndeclaredExceptions(bindInjector);
  }
  
  public void testUndeclaredExceptions_Provides() throws Exception {
    tUndeclaredExceptions(providesInjector);
  }
  
  public void testUndeclaredExceptions_Cxtor() throws Exception {
    tUndeclaredExceptions(cxtorInjector);
  }

  private void tUndeclaredExceptions(Injector injector) throws Exception { 
    RemoteProvider<Foo> remoteProvider = 
        injector.getInstance(Key.get(remoteProviderOfFoo));
    mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("A"));
    MockFoo.nextToThrow = new IndexOutOfBoundsException("A");
    try {
      remoteProvider.get();
      fail();
    } catch (RuntimeException e) {
      assertEquals("A", e.getCause().getMessage());
    }

    // undeclared exceptions shouldn't be scoped
    mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("B"));
    MockFoo.nextToThrow = new IndexOutOfBoundsException("B");
    try {
      remoteProvider.get();
      fail();
    } catch (RuntimeException e) {
      assertEquals("B", e.getCause().getMessage());
    }
  }

  public void testThrowingProviderSubclassing() throws Exception {
    final SubMockRemoteProvider aProvider = new SubMockRemoteProvider();
    aProvider.setNextToReturn(new SimpleFoo("A"));

    bindInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, Foo.class)
            .to(aProvider);
      }
    });

    assertEquals("A",
        bindInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
  }

  static class SubMockRemoteProvider extends MockRemoteProvider<Foo> { }

  public void testBindingToNonInterfaceType_Bind() throws Exception {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(MockRemoteProvider.class, Foo.class)
              .to(mockRemoteProvider);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertEquals(MockRemoteProvider.class.getName() + " must be an interface",
          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
    }
  }
  
  public void testBindingToNonInterfaceType_Provides() throws Exception {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
          
        @SuppressWarnings("unused")
        @CheckedProvides(MockRemoteProvider.class)
        Foo foo() {
          return null;
        }
      });
      fail();
    } catch (CreationException expected) {
      assertEquals(MockRemoteProvider.class.getName() + " must be an interface",
          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
    }
  }  
  
  public void testBindingToSubSubInterface_Bind() throws Exception {
    try {
      bindInjector = Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(SubRemoteProvider.class, Foo.class);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)",
          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
    }
  }
  
  public void testBindingToSubSubInterface_Provides() throws Exception {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
          
        @SuppressWarnings("unused")
        @CheckedProvides(SubRemoteProvider.class)
        Foo foo() {
          return null;
        }
      });
      fail();
    } catch (CreationException expected) {
      assertEquals(SubRemoteProvider.class.getName() + " must extend CheckedProvider (and only CheckedProvider)",
          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
    }
  }    

  interface SubRemoteProvider extends RemoteProvider<String> { }

  public void testBindingToInterfaceWithExtraMethod_Bind() throws Exception {
    try {
      bindInjector = Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(RemoteProviderWithExtraMethod.class, Foo.class);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " 
          + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(),
          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
    }
  }
  
  public void testBindingToInterfaceWithExtraMethod_Provides() throws Exception {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
          
        @SuppressWarnings("unused")
        @CheckedProvides(RemoteProviderWithExtraMethod.class)
        Foo foo() {
          return null;
        }
      });
      fail();
    } catch (CreationException expected) {
      assertEquals(RemoteProviderWithExtraMethod.class.getName() + " may not declare any new methods, but declared " 
          + RemoteProviderWithExtraMethod.class.getDeclaredMethods()[0].toGenericString(),
          Iterables.getOnlyElement(expected.getErrorMessages()).getMessage());
    }
  }
  
  public void testDependencies_Bind() {
    bindInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String.class).toInstance("Foo");
        bind(Integer.class).toInstance(5);
        bind(Double.class).toInstance(5d);
        bind(Long.class).toInstance(5L);
        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, Foo.class)
            .to(DependentRemoteProvider.class);
      }
    });
    
    HasDependencies hasDependencies =
        (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfFoo));
    hasDependencies = 
        (HasDependencies)bindInjector.getBinding(
            Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
    // Make sure that that is dependent on DependentRemoteProvider.
    assertEquals(Dependency.get(Key.get(DependentRemoteProvider.class)), 
        Iterables.getOnlyElement(hasDependencies.getDependencies()));
    // And make sure DependentRemoteProvider has the proper dependencies.
    hasDependencies = (HasDependencies)bindInjector.getBinding(DependentRemoteProvider.class);
    Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
        Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
    assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
        Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
  }
  
  public void testDependencies_Provides() {
    providesInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String.class).toInstance("Foo");
        bind(Integer.class).toInstance(5);
        bind(Double.class).toInstance(5d);
        bind(Long.class).toInstance(5L);
        install(ThrowingProviderBinder.forModule(this));
      }
      
      @SuppressWarnings("unused")
      @CheckedProvides(RemoteProvider.class)
      Foo foo(String s, Integer i, Double d, Long l) {
        return null;
      }
    });
    
    HasDependencies hasDependencies =
        (HasDependencies) providesInjector.getBinding(Key.get(remoteProviderOfFoo));
    // RemoteProvider<String> is dependent on the provider method..
    hasDependencies = (HasDependencies) providesInjector.getBinding(
        Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
    // And the provider method has our real dependencies..
    hasDependencies = (HasDependencies)providesInjector.getBinding(
        Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
    Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
        Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
    assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
        Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
  }  
  
  public void testDependencies_Cxtor() {
    cxtorInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String.class).toInstance("Foo");
        bind(Integer.class).toInstance(5);
        bind(Double.class).toInstance(5d);
        bind(Long.class).toInstance(5L);
        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, Foo.class)
            .providing(DependentMockFoo.class);
      }
    });
    
    Key<?> key = Key.get(remoteProviderOfFoo);
    
    // RemoteProvider<String> is dependent on Result.
    HasDependencies hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
    key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
    assertEquals(Result.class, key.getTypeLiteral().getRawType());

    // Result is dependent on the fake CheckedProvider impl
    hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
    key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
    assertTrue(CheckedProvider.class.isAssignableFrom(key.getTypeLiteral().getRawType()));
    
    // And the CheckedProvider is dependent on DependentMockFoo...
    hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
    key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
    assertEquals(DependentMockFoo.class, key.getTypeLiteral().getRawType());
    
    // And DependentMockFoo is dependent on the goods.
    hasDependencies = (HasDependencies) cxtorInjector.getBinding(key); 
    Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
        Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY));
    assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
        Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
  }  

  interface RemoteProviderWithExtraMethod<T> extends CheckedProvider<T> {
    T get(T defaultValue) throws RemoteException, BindException;
  }

  interface RemoteProvider<T> extends CheckedProvider<T> { 
    public T get() throws RemoteException, BindException;
  }
  
  static class DependentMockFoo implements Foo {
    @Inject double foo;
    
    @ThrowingInject public DependentMockFoo(String foo, int bar) {
    }
    
    @Inject void initialize(long foo) {}
    
    @Override
    public String s() {
      return null;
    }
  }
  
  static class DependentRemoteProvider<T> implements RemoteProvider<T> {
    @Inject double foo;
    
    @Inject public DependentRemoteProvider(String foo, int bar) {
    }
    
    @Inject void initialize(long foo) {}
    
    public T get() {
      return null;
    }
  }
  
  interface Foo {
    String s();
  }
  
  static class SimpleFoo implements Foo {
    private String s;
    
    SimpleFoo(String s) {
      this.s = s;
    }
    
    @Override
    public String s() {
      return s;
    }
    
    @Override
    public String toString() {
      return s;
    }
  }
  
  static class MockFoo implements Foo {
    static Exception nextToThrow;    
    static String nextToReturn;
    
    @ThrowingInject
    MockFoo() throws RemoteException, BindException {
      if (nextToThrow instanceof RemoteException) {
        throw (RemoteException) nextToThrow;
      } else if (nextToThrow instanceof BindException) {
        throw (BindException) nextToThrow;
      } else if (nextToThrow instanceof RuntimeException) {
        throw (RuntimeException) nextToThrow;
      } else if (nextToThrow == null) {
        // Do nothing, return this.
      } else {
        throw new AssertionError("nextToThrow must be a runtime or remote exception");
      }
    }
    
    @Override
    public String s() {
      return nextToReturn;
    }
    
    @Override
    public String toString() {
      return nextToReturn;
    }
  }
  
  static class AnotherMockFoo implements Foo {
    static Exception nextToThrow;    
    static String nextToReturn;
    
    @ThrowingInject
    AnotherMockFoo() throws RemoteException, BindException {
      if (nextToThrow instanceof RemoteException) {
        throw (RemoteException) nextToThrow;
      } else if (nextToThrow instanceof BindException) {
        throw (BindException) nextToThrow;
      } else if (nextToThrow instanceof RuntimeException) {
        throw (RuntimeException) nextToThrow;
      } else if (nextToThrow == null) {
        // Do nothing, return this.
      } else {
        throw new AssertionError("nextToThrow must be a runtime or remote exception");
      }
    }
    
    @Override
    public String s() {
      return nextToReturn;
    }
    
    @Override
    public String toString() {
      return nextToReturn;
    }
  }
  
  static class MockRemoteProvider<T> implements RemoteProvider<T> {
    Exception nextToThrow;
    T nextToReturn;

    public void throwOnNextGet(Exception nextToThrow) {
      this.nextToThrow = nextToThrow;
    }

    public void setNextToReturn(T nextToReturn) {
      this.nextToReturn = nextToReturn;
    }
    
    public T get() throws RemoteException, BindException {
      if (nextToThrow instanceof RemoteException) {
        throw (RemoteException) nextToThrow;
      } else if (nextToThrow instanceof BindException) {
        throw (BindException) nextToThrow;
      } else if (nextToThrow instanceof RuntimeException) {
        throw (RuntimeException) nextToThrow;
      } else if (nextToThrow == null) {
        return nextToReturn;
      } else {
        throw new AssertionError("nextToThrow must be a runtime or remote exception");
      }
    }
  }

  public void testBindingToInterfaceWithBoundValueType_Bind() throws RemoteException {
    bindInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        ThrowingProviderBinder.create(binder())
            .bind(StringRemoteProvider.class, String.class)
            .to(new StringRemoteProvider() {
              public String get() {
                return "A";
              }
            });
      }
    });
    
    assertEquals("A", bindInjector.getInstance(StringRemoteProvider.class).get());
  }
  
  public void testBindingToInterfaceWithBoundValueType_Provides() throws RemoteException {
    providesInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        install(ThrowingProviderBinder.forModule(this));
      }
      
      @SuppressWarnings("unused")
      @CheckedProvides(StringRemoteProvider.class)
      String foo() throws RemoteException {
          return "A";
      }
    });
    
    assertEquals("A", providesInjector.getInstance(StringRemoteProvider.class).get());
  }

  interface StringRemoteProvider extends CheckedProvider<String> {
    @Override String get() throws RemoteException;  
  }

  @SuppressWarnings("deprecation")
  public void testBindingToInterfaceWithGeneric_Bind() throws Exception {
    bindInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, new TypeLiteral<List<String>>() { }.getType())
            .to(new RemoteProvider<List<String>>() {
              public List<String> get() {
                return Arrays.asList("A", "B");
              }
            });
      }
    });

    Key<RemoteProvider<List<String>>> key
        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
    assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
  }
  
  public void testBindingToInterfaceWithGeneric_BindUsingTypeLiteral() throws Exception {
    bindInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, new TypeLiteral<List<String>>() {})
            .to(new RemoteProvider<List<String>>() {
              public List<String> get() {
                return Arrays.asList("A", "B");
              }
            });
      }
    });

    Key<RemoteProvider<List<String>>> key
        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
    assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
  }
  
  public void testBindingToInterfaceWithGeneric_Provides() throws Exception {
    providesInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        install(ThrowingProviderBinder.forModule(this));
      }
      
      @SuppressWarnings("unused")
      @CheckedProvides(RemoteProvider.class)
      List<String> foo() throws RemoteException {
          return Arrays.asList("A", "B");
      }
    });

    Key<RemoteProvider<List<String>>> key
        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
    assertEquals(Arrays.asList("A", "B"), providesInjector.getInstance(key).get());
  }
  
  public void testBindingToInterfaceWithGeneric_Cxtor() throws Exception {
    cxtorInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        ThrowingProviderBinder.create(binder())
        .bind(RemoteProvider.class, new TypeLiteral<List<String>>() {})
        .providing(new TypeLiteral<ThrowingArrayList<String>>() {});
      }
    });

    Key<RemoteProvider<List<String>>> key
        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
    assertEquals(Arrays.asList(), cxtorInjector.getInstance(key).get());
  }
  
  private static class ThrowingArrayList<T> extends ArrayList<T> {
    @SuppressWarnings("unused")
    @ThrowingInject
    ThrowingArrayList() {}
  }
  
  public void testProviderMethodWithWrongException() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
        
        @SuppressWarnings("unused")
        @CheckedProvides(RemoteProvider.class)
        String foo() throws InterruptedException {
            return null;
        }
      });
      fail();
    } catch(CreationException ce) {
      assertEquals(InterruptedException.class.getName()
          + " is not compatible with the exceptions (["
          + RemoteException.class + ", " + BindException.class
          + "]) declared in the CheckedProvider interface ("
          + RemoteProvider.class.getName()
          + ")", 
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  public void testCxtorWithWrongException() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(RemoteProvider.class, Foo.class)
              .providing(WrongExceptionFoo.class);
        }
      });
      fail();
    } catch (CreationException ce) {
      assertEquals(InterruptedException.class.getName()
          + " is not compatible with the exceptions (["
          + RemoteException.class + ", " + BindException.class
          + "]) declared in the CheckedProvider interface ("
          + RemoteProvider.class.getName()
          + ")", 
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  static class WrongExceptionFoo implements Foo {
    @SuppressWarnings("unused")
    @ThrowingInject
    public WrongExceptionFoo() throws InterruptedException {
    }
    
    @Override
    public String s() { return null; }
  }
  
  public void testProviderMethodWithSubclassOfExceptionIsOk() throws Exception {
    providesInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        install(ThrowingProviderBinder.forModule(this));
      }
      
      @SuppressWarnings("unused")
      @CheckedProvides(RemoteProvider.class)
      Foo foo() throws AccessException {
        throw new AccessException("boo!");
      }
    });
    
    RemoteProvider<Foo> remoteProvider = 
      providesInjector.getInstance(Key.get(remoteProviderOfFoo));

    try {
      remoteProvider.get();
      fail();
    } catch (RemoteException expected) {
      assertTrue(expected instanceof AccessException);
      assertEquals("boo!", expected.getMessage());
    }
  }
  
  public void testCxtorWithSubclassOfExceptionIsOk() throws Exception {
    cxtorInjector = Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(RemoteProvider.class, Foo.class)
              .providing(SubclassExceptionFoo.class);
        }
      });
    
    RemoteProvider<Foo> remoteProvider = 
        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));

      try {
        remoteProvider.get();
        fail();
      } catch (RemoteException expected) {
        assertTrue(expected instanceof AccessException);
        assertEquals("boo!", expected.getMessage());
      }
  }
  
  static class SubclassExceptionFoo implements Foo {
    @ThrowingInject
    public SubclassExceptionFoo() throws AccessException {
      throw new AccessException("boo!");
    }
    
    @Override
    public String s() { return null; }
  }
  
  public void testProviderMethodWithSuperclassExceptionFails() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
        
        @SuppressWarnings("unused")
        @CheckedProvides(RemoteProvider.class)
        Foo foo() throws IOException {
            return null;
        }
      });
      fail();
    } catch(CreationException ce) {
      assertEquals(IOException.class.getName()
          + " is not compatible with the exceptions (["
          + RemoteException.class + ", " + BindException.class
          + "]) declared in the CheckedProvider interface ("
          + RemoteProvider.class.getName()
          + ")", 
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  public void testCxtorWithSuperclassExceptionFails() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(RemoteProvider.class, Foo.class)
              .providing(SuperclassExceptionFoo.class);
        }
      });
      fail();
    } catch (CreationException ce) {
      assertEquals(IOException.class.getName()
          + " is not compatible with the exceptions (["
          + RemoteException.class + ", " + BindException.class
          + "]) declared in the CheckedProvider interface ("
          + RemoteProvider.class.getName()
          + ")", 
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  static class SuperclassExceptionFoo implements Foo {
    @SuppressWarnings("unused")
    @ThrowingInject
    public SuperclassExceptionFoo() throws IOException {
    }
    
    @Override
    public String s() { return null; }
  }
  
  public void testProviderMethodWithRuntimeExceptionsIsOk() throws Exception {
    providesInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        install(ThrowingProviderBinder.forModule(this));
      }
      
      @SuppressWarnings("unused")
      @CheckedProvides(RemoteProvider.class)
      Foo foo() throws RuntimeException {
        throw new RuntimeException("boo!");
      }
    });
    
    RemoteProvider<Foo> remoteProvider = 
      providesInjector.getInstance(Key.get(remoteProviderOfFoo));

    try {
      remoteProvider.get();
      fail();
    } catch (RuntimeException expected) {
      assertEquals("boo!", expected.getCause().getMessage());
    }
  }
  
  public void testCxtorWithRuntimeExceptionsIsOk() throws Exception {
    cxtorInjector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        ThrowingProviderBinder.create(binder())
            .bind(RemoteProvider.class, Foo.class)
            .providing(RuntimeExceptionFoo.class);
      }
    });
    
    RemoteProvider<Foo> remoteProvider = 
        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));

    try {
      remoteProvider.get();
      fail();
    } catch (RuntimeException expected) {
      assertEquals("boo!", expected.getCause().getMessage());
    }
  }
    
  static class RuntimeExceptionFoo implements Foo {
    @ThrowingInject
    public RuntimeExceptionFoo() throws RuntimeException {
      throw new RuntimeException("boo!");
    }
    
    @Override
    public String s() { return null; }
  }
  
  private static class SubBindException extends BindException {}
  
  public void testProviderMethodWithManyExceptions() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
        
        @SuppressWarnings("unused")
        @CheckedProvides(RemoteProvider.class)
        String foo() throws InterruptedException, RuntimeException, RemoteException, 
                            AccessException, TooManyListenersException,
                            BindException, SubBindException {
            return null;
        }
      });
      fail();
    } catch(CreationException ce) {
      // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK.
      List<Message> errors = ImmutableList.copyOf(ce.getErrorMessages());
      assertEquals(InterruptedException.class.getName()
          + " is not compatible with the exceptions (["
          + RemoteException.class + ", " + BindException.class
          + "]) declared in the CheckedProvider interface ("
          + RemoteProvider.class.getName()
          + ")", 
          errors.get(0).getMessage());
      assertEquals(TooManyListenersException.class.getName()
          + " is not compatible with the exceptions (["
          + RemoteException.class + ", " + BindException.class
          + "]) declared in the CheckedProvider interface ("
          + RemoteProvider.class.getName()
          + ")", 
          errors.get(1).getMessage());
      assertEquals(2, errors.size());
    }
  }
  
  public void testCxtorWithManyExceptions() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(RemoteProvider.class, Foo.class)
              .providing(ManyExceptionFoo.class);
        }
      });
      fail();
    } catch (CreationException ce) {
      // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK.
      List<Message> errors = ImmutableList.copyOf(ce.getErrorMessages());
      assertEquals(InterruptedException.class.getName()
          + " is not compatible with the exceptions (["
          + RemoteException.class + ", " + BindException.class
          + "]) declared in the CheckedProvider interface ("
          + RemoteProvider.class.getName()
          + ")", 
          errors.get(0).getMessage());
      assertEquals(TooManyListenersException.class.getName()
          + " is not compatible with the exceptions (["
          + RemoteException.class + ", " + BindException.class
          + "]) declared in the CheckedProvider interface ("
          + RemoteProvider.class.getName()
          + ")", 
          errors.get(1).getMessage());
      assertEquals(2, errors.size());
    }
  }
  
  static class ManyExceptionFoo implements Foo {
    @SuppressWarnings("unused")
    @ThrowingInject
    public ManyExceptionFoo()
        throws InterruptedException,
        RuntimeException,
        RemoteException,
        AccessException,
        TooManyListenersException,
        BindException,
        SubBindException {
    }
    
    @Override
    public String s() { return null; }
  }
  
  public void testMoreTypeParameters() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
        
        @SuppressWarnings("unused")
        @CheckedProvides(TooManyTypeParameters.class)
        String foo() {
            return null;
        }
      });
      fail();
    } catch(CreationException ce) {
      assertEquals(TooManyTypeParameters.class.getName() + " has more than one generic type parameter: [T, P]",
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }    
  }
  
  public void testWrongThrowingProviderType() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
        
        @SuppressWarnings("unused")
        @CheckedProvides(WrongThrowingProviderType.class)
        String foo() {
            return null;
        }
      });
      fail();
    } catch(CreationException ce) {
      assertEquals(WrongThrowingProviderType.class.getName() 
          + " does not properly extend CheckedProvider, the first type parameter of CheckedProvider "
          + "(java.lang.String) is not a generic type",
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }    
  }
  
  public void testOneMethodThatIsntGet() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
        
        @SuppressWarnings("unused")
        @CheckedProvides(OneNoneGetMethod.class)
        String foo() {
            return null;
        }
      });
      fail();
    } catch(CreationException ce) {
      assertEquals(OneNoneGetMethod.class.getName() 
          + " may not declare any new methods, but declared " + Classes.toString(OneNoneGetMethod.class.getDeclaredMethods()[0]),
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  public void testManyMethods() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
        
        @SuppressWarnings("unused")
        @CheckedProvides(ManyMethods.class)
        String foo() {
            return null;
        }
      });
      fail();
    } catch(CreationException ce) {
      assertEquals(ManyMethods.class.getName() 
          + " may not declare any new methods, but declared " + Arrays.asList(ManyMethods.class.getDeclaredMethods()),
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  public void testIncorrectPredefinedType_Bind() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(StringRemoteProvider.class, Integer.class)
              .to(new StringRemoteProvider() {
                public String get() {
                  return "A";
                }
              });
        }
      });
      fail();
    } catch(CreationException ce) {
      assertEquals(StringRemoteProvider.class.getName() 
          + " expects the value type to be java.lang.String, but it was java.lang.Integer",
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  public void testIncorrectPredefinedType_Provides() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          install(ThrowingProviderBinder.forModule(this));
        }
        
        @SuppressWarnings("unused")
        @CheckedProvides(StringRemoteProvider.class)
        Integer foo() {
            return null;
        }
      });
      fail();
    } catch(CreationException ce) {
      assertEquals(StringRemoteProvider.class.getName() 
          + " expects the value type to be java.lang.String, but it was java.lang.Integer",
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  private static interface TooManyTypeParameters<T, P> extends CheckedProvider<T> {    
  }
  
  private static interface WrongThrowingProviderType<T> extends CheckedProvider<String> {    
  }
  
  private static interface OneNoneGetMethod<T> extends CheckedProvider<T> {
    T bar();
  }
  
  private static interface ManyMethods<T> extends CheckedProvider<T> {
    T bar();
    String baz();
  }
  
  public void testResultSerializes() throws Exception {
    Result result = Result.forValue("foo");
    result = Asserts.reserialize(result);
    assertEquals("foo", result.getOrThrow());
  }
  
  public void testResultExceptionSerializes() throws Exception {
    Result result = Result.forException(new Exception("boo"));
    result = Asserts.reserialize(result);
    try {
      result.getOrThrow();
      fail();
    } catch(Exception ex) {
      assertEquals("boo", ex.getMessage());
    }
  }
  
  public void testEarlyBindingError() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(StringRemoteProvider.class, String.class)
              .to(FailingProvider.class);
        }
      });
      fail();
    } catch(CreationException ce) {
      assertEquals("Could not find a suitable constructor in " + FailingProvider.class.getName()
          + ". Classes must have either one (and only one) constructor annotated with @Inject"
          + " or a zero-argument constructor that is not private.",
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  private static class FailingProvider implements StringRemoteProvider {
    // no @Inject.
    @SuppressWarnings("unused")
    FailingProvider(Integer foo) {}
    
    public String get() {
      return null;
    }
  }
  
  public void testNoInjectionPointForUsing() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(RemoteProvider.class, Foo.class)
              .providing(InvalidFoo.class);
        }
      });
      fail();
    } catch (CreationException ce) {
      assertEquals("Could not find a suitable constructor in " + InvalidFoo.class.getName()
          + ". Classes must have either one (and only one) constructor annotated with "
          + "@ThrowingInject.",
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  static class InvalidFoo implements Foo {
    public InvalidFoo(String dep) {
    }
    
    @Override public String s() { return null; }
  }
  
  public void testNoThrowingInject() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(RemoteProvider.class, Foo.class)
              .providing(NormalInjectableFoo.class);
        }
      });
      fail();
    } catch (CreationException ce) {
      assertEquals("Could not find a suitable constructor in " + NormalInjectableFoo.class.getName()
          + ". Classes must have either one (and only one) constructor annotated with "
          + "@ThrowingInject.",
          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
    }
  }
  
  static class NormalInjectableFoo implements Foo {
    @Inject
    public NormalInjectableFoo() {
    }
    
    @Override public String s() { return null; }
  }
  
  public void testProvisionExceptionOnDependenciesOfCxtor() throws Exception {
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(RemoteProvider.class, Foo.class)
              .providing(ProvisionExceptionFoo.class);
          bindScope(BadScope.class, new Scope() {
            @Override
            public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) {
              return new Provider<T>() {
                @Override
                public T get() {
                  throw new OutOfScopeException("failure");
                }
              };
            }
          });
        }
      });
    
    try {
      injector.getInstance(Key.get(remoteProviderOfFoo)).get();
      fail();
    } catch(ProvisionException pe) {
      assertEquals(2, pe.getErrorMessages().size());
      List<Message> messages = Lists.newArrayList(pe.getErrorMessages());
      assertEquals("Error in custom provider, com.google.inject.OutOfScopeException: failure",
          messages.get(0).getMessage());
      assertEquals("Error in custom provider, com.google.inject.OutOfScopeException: failure",
          messages.get(1).getMessage());
    }
  }
  
  @ScopeAnnotation
  @Target(ElementType.TYPE)
  @Retention(RetentionPolicy.RUNTIME)
  private @interface BadScope { }
  
  @BadScope private static class Unscoped1 {}
  @BadScope private static class Unscoped2 {}
  
  static class ProvisionExceptionFoo implements Foo {
    @ThrowingInject
    public ProvisionExceptionFoo(Unscoped1 a, Unscoped2 b) {
    }
    
    @Override public String s() { return null; }
  }
  
  public void testUsingDoesntClashWithBindingsOfSameType() throws Exception {
    cxtorInjector = Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          ThrowingProviderBinder.create(binder())
              .bind(RemoteProvider.class, Foo.class)
              .providing(MockFoo.class);
          bind(Foo.class).to(MockFoo.class);
          bind(MockFoo.class).to(SubMockFoo.class);
        }
      });
    
    RemoteProvider<Foo> remoteProvider = 
        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
    Foo providerGot = remoteProvider.get();
    Foo fooGot = cxtorInjector.getInstance(Foo.class);
    Foo mockGot = cxtorInjector.getInstance(MockFoo.class);
    
    assertEquals(MockFoo.class, providerGot.getClass());
    assertEquals(SubMockFoo.class, fooGot.getClass());
    assertEquals(SubMockFoo.class, mockGot.getClass());
  }
  
  static class SubMockFoo extends MockFoo {
    public SubMockFoo() throws RemoteException, BindException {
    }
    
  }
}
