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

import static com.google.inject.Asserts.asModuleChain;
import static com.google.inject.Asserts.assertContains;
import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH;
import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE;
import static com.google.inject.multibindings.SpiUtils.assertMapVisitor;
import static com.google.inject.multibindings.SpiUtils.instance;
import static com.google.inject.multibindings.SpiUtils.providerInstance;
import static com.google.inject.name.Names.named;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.AbstractModule;
import com.google.inject.Binding;
import com.google.inject.BindingAnnotation;
import com.google.inject.ConfigurationException;
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.Module;
import com.google.inject.Provider;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.WeakKeySetUtils;
import com.google.inject.name.Names;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.InstanceBinding;
import com.google.inject.util.Modules;
import com.google.inject.util.Providers;
import com.google.inject.util.Types;

import junit.framework.TestCase;

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.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author dpb@google.com (David P. Baker)
 */
public class MapBinderTest extends TestCase {

  private static final Set<Key<?>> FRAMEWORK_KEYS = ImmutableSet.of(
      Key.get(java.util.logging.Logger.class),
      Key.get(Stage.class),
      Key.get(Injector.class)
  );

  final TypeLiteral<Map<String, javax.inject.Provider<String>>> mapOfStringJavaxProvider =
      new TypeLiteral<Map<String, javax.inject.Provider<String>>>() {};
  final TypeLiteral<Map<String, Provider<String>>> mapOfStringProvider =
      new TypeLiteral<Map<String, Provider<String>>>() {}; 
  final TypeLiteral<Map<String, String>> mapOfString = new TypeLiteral<Map<String, String>>() {};
  final TypeLiteral<Map<Integer, String>> mapOfIntString =
      new TypeLiteral<Map<Integer, String>>() {};
  final TypeLiteral<Map<String, Integer>> mapOfInteger = new TypeLiteral<Map<String, Integer>>() {};
  final TypeLiteral<Map<String, Set<String>>> mapOfSetOfString =
      new TypeLiteral<Map<String, Set<String>>>() {};
      
  private final TypeLiteral<String> stringType = TypeLiteral.get(String.class);
  private final TypeLiteral<Integer> intType = TypeLiteral.get(Integer.class);

  private Type javaxProviderOf(Type type) {
    return Types.newParameterizedType(javax.inject.Provider.class, type);
  }

  private Type mapEntryOf(Type keyType, Type valueType) {
    return Types.newParameterizedTypeWithOwner(Map.class, Map.Entry.class, keyType, valueType);
  }

  private Type collectionOf(Type type) {
    return Types.newParameterizedType(Collection.class, type);
  }

  public void testAllBindings() {
    Module module = new AbstractModule() {
      @Override
      protected void configure() {
        MapBinder.newMapBinder(binder(), String.class, String.class).permitDuplicates();
      }
    };

    Injector injector = Guice.createInjector(module);

    Map<Key<?>, Binding<?>> bindings = injector.getBindings();

    ImmutableSet<Key<?>> expectedBindings = ImmutableSet.<Key<?>>builder()
        .add(
            // Map<K, V>
            Key.get(Types.mapOf(String.class, String.class)),
            // Map<K, Provider<V>>
            Key.get(Types.mapOf(String.class, Types.providerOf(String.class))),
            // Map<K, javax.inject.Provider<V>>
            Key.get(Types.mapOf(String.class, javaxProviderOf(String.class))),
            // Map<K, Set<V>>
            Key.get(Types.mapOf(String.class, Types.setOf(String.class))),
            // Map<K, Set<Provider<V>>
            Key.get(Types.mapOf(String.class, Types.setOf(Types.providerOf(String.class)))),
            // Set<Map.Entry<K, Provider<V>>>
            Key.get(Types.setOf(mapEntryOf(String.class, Types.providerOf(String.class)))),
            // Collection<Provider<Map.Entry<K, Provider<V>>>>
            Key.get(collectionOf(Types.providerOf(
                mapEntryOf(String.class, Types.providerOf(String.class))))),
            // Collection<javax.inject.Provider<Map.Entry<K, Provider<V>>>>
            Key.get(collectionOf(javaxProviderOf(
                mapEntryOf(String.class, Types.providerOf(String.class))))),
            // @Named(...) Boolean
            Key.get(Boolean.class,
                named("Multibinder<java.util.Map$Entry<java.lang.String, "
                    + "com.google.inject.Provider<java.lang.String>>> permits duplicates"))
        )
        .addAll(FRAMEWORK_KEYS).build();

    Set<Key<?>> missingBindings = Sets.difference(expectedBindings, bindings.keySet());
    Set<Key<?>> extraBindings = Sets.difference(bindings.keySet(), expectedBindings);

    assertTrue("There should be no missing bindings. Missing: " + missingBindings,
        missingBindings.isEmpty());
    assertTrue("There should be no extra bindings. Extra: " + extraBindings,
        extraBindings.isEmpty());
  }

  public void testMapBinderAggregatesMultipleModules() {
    Module abc = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class);
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("b").toInstance("B");
        multibinder.addBinding("c").toInstance("C");
      }
    };
    Module de = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class);
        multibinder.addBinding("d").toInstance("D");
        multibinder.addBinding("e").toInstance("E");
      }
    };

    Injector injector = Guice.createInjector(abc, de);
    Map<String, String> abcde = injector.getInstance(Key.get(mapOfString));

    assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E"), abcde);
    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abc, de), BOTH, false, 0,
        instance("a", "A"), instance("b", "B"), instance("c", "C"), instance("d", "D"), instance("e", "E"));

    // just make sure these succeed
    injector.getInstance(Key.get(mapOfStringProvider));
    injector.getInstance(Key.get(mapOfStringJavaxProvider));
  }

  public void testMapBinderAggregationForAnnotationInstance() {
    Module module = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class, Names.named("abc"));
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("b").toInstance("B");

        multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class, Names.named("abc"));
        multibinder.addBinding("c").toInstance("C");
      }
    };
    Injector injector = Guice.createInjector(module);

    Key<Map<String, String>> key = Key.get(mapOfString, Names.named("abc"));
    Map<String, String> abc = injector.getInstance(key);
    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc);
    assertMapVisitor(key, stringType, stringType, setOf(module), BOTH, false, 0,
        instance("a", "A"), instance("b", "B"), instance("c", "C"));
    
    // just make sure these succeed
    injector.getInstance(Key.get(mapOfStringProvider, Names.named("abc")));
    injector.getInstance(Key.get(mapOfStringJavaxProvider, Names.named("abc")));
  }

  public void testMapBinderAggregationForAnnotationType() {
    Module module = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class, Abc.class);
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("b").toInstance("B");

        multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class, Abc.class);
        multibinder.addBinding("c").toInstance("C");
      }
    };
    Injector injector = Guice.createInjector(module);

    Key<Map<String, String>> key = Key.get(mapOfString, Abc.class);
    Map<String, String> abc = injector.getInstance(key);
    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc);
    assertMapVisitor(key, stringType, stringType, setOf(module), BOTH, false, 0,
        instance("a", "A"), instance("b", "B"), instance("c", "C"));
    
    // just make sure these succeed
    injector.getInstance(Key.get(mapOfStringProvider, Abc.class));
    injector.getInstance(Key.get(mapOfStringJavaxProvider, Abc.class));
  }

  public void testMapBinderWithMultipleAnnotationValueSets() {
    Module module = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> abcMapBinder = MapBinder.newMapBinder(
            binder(), String.class, String.class, named("abc"));
        abcMapBinder.addBinding("a").toInstance("A");
        abcMapBinder.addBinding("b").toInstance("B");
        abcMapBinder.addBinding("c").toInstance("C");

        MapBinder<String, String> deMapBinder = MapBinder.newMapBinder(
            binder(), String.class, String.class, named("de"));
        deMapBinder.addBinding("d").toInstance("D");
        deMapBinder.addBinding("e").toInstance("E");
      }
    };
    Injector injector = Guice.createInjector(module);

    Key<Map<String, String>> abcKey = Key.get(mapOfString, named("abc"));
    Map<String, String> abc = injector.getInstance(abcKey);
    Key<Map<String, String>> deKey = Key.get(mapOfString, named("de"));
    Map<String, String> de = injector.getInstance(deKey);
    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc);
    assertEquals(mapOf("d", "D", "e", "E"), de);
    assertMapVisitor(abcKey, stringType, stringType, setOf(module), BOTH, false, 1,
        instance("a", "A"), instance("b", "B"), instance("c", "C"));
    assertMapVisitor(deKey, stringType, stringType, setOf(module), BOTH, false, 1,
        instance("d", "D"), instance("e", "E"));     
    
    // just make sure these succeed
    injector.getInstance(Key.get(mapOfStringProvider, named("abc")));
    injector.getInstance(Key.get(mapOfStringJavaxProvider, named("abc")));
    injector.getInstance(Key.get(mapOfStringProvider, named("de")));
    injector.getInstance(Key.get(mapOfStringJavaxProvider, named("de")));
  }

  public void testMapBinderWithMultipleAnnotationTypeSets() {
    Module module = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> abcMapBinder = MapBinder.newMapBinder(
            binder(), String.class, String.class, Abc.class);
        abcMapBinder.addBinding("a").toInstance("A");
        abcMapBinder.addBinding("b").toInstance("B");
        abcMapBinder.addBinding("c").toInstance("C");

        MapBinder<String, String> deMapBinder = MapBinder.newMapBinder(
            binder(), String.class, String.class, De.class);
        deMapBinder.addBinding("d").toInstance("D");
        deMapBinder.addBinding("e").toInstance("E");
      }
    };
    Injector injector = Guice.createInjector(module);

    Key<Map<String, String>> abcKey = Key.get(mapOfString, Abc.class);
    Map<String, String> abc = injector.getInstance(abcKey);
    Key<Map<String, String>> deKey = Key.get(mapOfString, De.class);
    Map<String, String> de = injector.getInstance(deKey);
    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), abc);
    assertEquals(mapOf("d", "D", "e", "E"), de);
    assertMapVisitor(abcKey, stringType, stringType, setOf(module), BOTH, false, 1,
        instance("a", "A"), instance("b", "B"), instance("c", "C"));
    assertMapVisitor(deKey, stringType, stringType, setOf(module), BOTH, false, 1,
        instance("d", "D"), instance("e", "E"));
    
    // just make sure these succeed
    injector.getInstance(Key.get(mapOfStringProvider, Abc.class));
    injector.getInstance(Key.get(mapOfStringJavaxProvider, Abc.class));
    injector.getInstance(Key.get(mapOfStringProvider, De.class));
    injector.getInstance(Key.get(mapOfStringJavaxProvider, De.class));
  }

  public void testMapBinderWithMultipleTypes() {
    Module module = new AbstractModule() {
      @Override protected void configure() {
        MapBinder.newMapBinder(binder(), String.class, String.class)
            .addBinding("a").toInstance("A");
        MapBinder.newMapBinder(binder(), String.class, Integer.class)
            .addBinding("1").toInstance(1);
      }
    };
    Injector injector = Guice.createInjector(module);

    assertEquals(mapOf("a", "A"), injector.getInstance(Key.get(mapOfString)));
    assertEquals(mapOf("1", 1), injector.getInstance(Key.get(mapOfInteger)));
    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 1,
        instance("a", "A"));
    assertMapVisitor(Key.get(mapOfInteger), stringType, intType, setOf(module), BOTH, false, 1,
        instance("1", 1));
  }

  public void testMapBinderWithEmptyMap() {
    Module module = new AbstractModule() {
      @Override protected void configure() {
        MapBinder.newMapBinder(binder(), String.class, String.class);
      }
    };
    Injector injector = Guice.createInjector(module);

    Map<String, String> map = injector.getInstance(Key.get(mapOfString));
    assertEquals(Collections.emptyMap(), map);
    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 0);
  }

  public void testMapBinderMapIsUnmodifiable() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        MapBinder.newMapBinder(binder(), String.class, String.class)
            .addBinding("a").toInstance("A");
      }
    });

    Map<String, String> map = injector.getInstance(Key.get(mapOfString));
    try {
      map.clear();
      fail();
    } catch(UnsupportedOperationException expected) {
    }
  }

  public void testMapBinderMapIsLazy() {
    Module module = new AbstractModule() {
      @Override protected void configure() {
        MapBinder.newMapBinder(binder(), String.class, Integer.class)
            .addBinding("num").toProvider(new Provider<Integer>() {
          int nextValue = 1;
          @Override public Integer get() {
            return nextValue++;
          }
        });
      }
    };
    Injector injector = Guice.createInjector(module);

    assertEquals(mapOf("num", 1), injector.getInstance(Key.get(mapOfInteger)));
    assertEquals(mapOf("num", 2), injector.getInstance(Key.get(mapOfInteger)));
    assertEquals(mapOf("num", 3), injector.getInstance(Key.get(mapOfInteger)));
    assertMapVisitor(Key.get(mapOfInteger), stringType, intType, setOf(module), BOTH, false, 0,
        providerInstance("num", 1));
  }

  public void testMapBinderMapForbidsDuplicateKeys() {
    Module module = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class);
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("a").toInstance("B");
      }
    };
    try {
      Guice.createInjector(module);
      fail();
    } catch(CreationException expected) {
      assertContains(expected.getMessage(),
          "Map injection failed due to duplicated key \"a\"");
    }
    
    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), MODULE, false, 0,
        instance("a", "A"), instance("a", "B"));
  }

  public void testExhaustiveDuplicateErrorMessage() throws Exception {
    class Module1 extends AbstractModule {
      @Override protected void configure() {
        MapBinder<String, Object> mapbinder =
            MapBinder.newMapBinder(binder(), String.class, Object.class);
        mapbinder.addBinding("a").to(String.class);
      }
    }
    class Module2 extends AbstractModule {
      @Override protected void configure() {
        MapBinder<String, Object> mapbinder =
            MapBinder.newMapBinder(binder(), String.class, Object.class);
        mapbinder.addBinding("a").to(Integer.class);
        mapbinder.addBinding("b").to(String.class);
      }
    }
    class Module3 extends AbstractModule {
      @Override protected void configure() {
        MapBinder<String, Object> mapbinder =
            MapBinder.newMapBinder(binder(), String.class, Object.class);
        mapbinder.addBinding("b").to(Integer.class);
      }
    }
    class Main extends AbstractModule {
      @Override protected void configure() {
        MapBinder.newMapBinder(binder(), String.class, Object.class);
        install(new Module1());
        install(new Module2());
        install(new Module3());
      }
      @Provides String provideString() { return "foo"; }
      @Provides Integer provideInt() { return 42; }
    }
    try {
      Guice.createInjector(new Main());
      fail();
    } catch(CreationException ce) {
      assertContains(ce.getMessage(),
          "Map injection failed due to duplicated key \"a\", from bindings:",
          asModuleChain(Main.class, Module1.class),
          asModuleChain(Main.class, Module2.class),
          "and key: \"b\", from bindings:",
          asModuleChain(Main.class, Module2.class),
          asModuleChain(Main.class, Module3.class),
          "at " + Main.class.getName() + ".configure(",
          asModuleChain(Main.class, MapBinder.RealMapBinder.class));
      assertEquals(1, ce.getErrorMessages().size());
    }
  }

  public void testMapBinderMapPermitDuplicateElements() {
    Module ab = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class);
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("b").toInstance("B");
        multibinder.permitDuplicates();
      }
    };
    Module bc = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class);
        multibinder.addBinding("b").toInstance("B");
        multibinder.addBinding("c").toInstance("C");
        multibinder.permitDuplicates();
      }
    };
    Injector injector = Guice.createInjector(ab, bc);

    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), injector.getInstance(Key.get(mapOfString)));
    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(ab, bc), BOTH, true, 0,
        instance("a", "A"), instance("b", "B"), instance("c", "C"));
  }

  public void testMapBinderMapDoesNotDedupeDuplicateValues() {
    class ValueType {
      int keyPart;
      int dataPart;
      private ValueType(int keyPart, int dataPart) {
        this.keyPart = keyPart;
        this.dataPart = dataPart;
      }
      @Override
      public boolean equals(Object obj) {
        return (obj instanceof ValueType) && (keyPart == ((ValueType) obj).keyPart);
      }
      @Override
      public int hashCode() {
        return keyPart;
      }
    }
    Module m1 = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, ValueType> multibinder = MapBinder.newMapBinder(
            binder(), String.class, ValueType.class);
        multibinder.addBinding("a").toInstance(new ValueType(1, 2));
      }
    };
    Module m2 = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, ValueType> multibinder = MapBinder.newMapBinder(
            binder(), String.class, ValueType.class);
        multibinder.addBinding("b").toInstance(new ValueType(1, 3));
      }
    };
    
    Injector injector = Guice.createInjector(m1, m2);
    Map<String, ValueType> map = injector.getInstance(new Key<Map<String, ValueType>>() {});
    assertEquals(2, map.get("a").dataPart);
    assertEquals(3, map.get("b").dataPart);
  }

  public void testMapBinderMultimap() {
    AbstractModule ab1c = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class);
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("b").toInstance("B1");
        multibinder.addBinding("c").toInstance("C");
      }
    };
    AbstractModule b2c = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class);
        multibinder.addBinding("b").toInstance("B2");
        multibinder.addBinding("c").toInstance("C");
        multibinder.permitDuplicates();
      }
    };
    Injector injector = Guice.createInjector(ab1c, b2c);

    assertEquals(mapOf("a", setOf("A"), "b", setOf("B1", "B2"), "c", setOf("C")),
        injector.getInstance(Key.get(mapOfSetOfString)));
    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(ab1c, b2c), BOTH, true, 0,
        instance("a", "A"), instance("b", "B1"), instance("b", "B2"), instance("c", "C"));
  }

  public void testMapBinderMultimapWithAnotation() {
    AbstractModule ab1 = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class, Abc.class);
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("b").toInstance("B1");
      }
    };
    AbstractModule b2c = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(
            binder(), String.class, String.class, Abc.class);
        multibinder.addBinding("b").toInstance("B2");
        multibinder.addBinding("c").toInstance("C");
        multibinder.permitDuplicates();
      }
    };
    Injector injector = Guice.createInjector(ab1, b2c);

    assertEquals(mapOf("a", setOf("A"), "b", setOf("B1", "B2"), "c", setOf("C")),
        injector.getInstance(Key.get(mapOfSetOfString, Abc.class)));
    try {
      injector.getInstance(Key.get(mapOfSetOfString));
      fail();
    } catch (ConfigurationException expected) {}
    
    assertMapVisitor(Key.get(mapOfString, Abc.class), stringType, stringType, setOf(ab1, b2c), BOTH, true, 0,
        instance("a", "A"), instance("b", "B1"), instance("b", "B2"), instance("c", "C"));
  }

  public void testMapBinderMultimapIsUnmodifiable() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> mapBinder = MapBinder.newMapBinder(
            binder(), String.class, String.class);
        mapBinder.addBinding("a").toInstance("A");
        mapBinder.permitDuplicates();
      }
    });

    Map<String, Set<String>> map = injector.getInstance(Key.get(mapOfSetOfString));
    try {
      map.clear();
      fail();
    } catch(UnsupportedOperationException expected) {
    }
    try {
      map.get("a").clear();
      fail();
    } catch(UnsupportedOperationException expected) {
    }
  }

  public void testMapBinderMapForbidsNullKeys() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          MapBinder.newMapBinder(binder(), String.class, String.class).addBinding(null);
        }
      });
      fail();
    } catch (CreationException expected) {}
  }

  public void testMapBinderMapForbidsNullValues() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        MapBinder.newMapBinder(binder(), String.class, String.class)
            .addBinding("null").toProvider(Providers.<String>of(null));
      }
    });

    try {
      injector.getInstance(Key.get(mapOfString));
      fail();
    } catch(ProvisionException expected) {
      assertContains(expected.getMessage(),
          "1) Map injection failed due to null value for key \"null\"");
    }
  }

  public void testMapBinderProviderIsScoped() {
    final Provider<Integer> counter = new Provider<Integer>() {
      int next = 1;
      @Override public Integer get() {
        return next++;
      }
    };

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        MapBinder.newMapBinder(binder(), String.class, Integer.class)
            .addBinding("one").toProvider(counter).asEagerSingleton();
      }
    });

    assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one"));
    assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one"));
  }

  public void testSourceLinesInMapBindings() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          MapBinder.newMapBinder(binder(), String.class, Integer.class)
              .addBinding("one");
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) No implementation for java.lang.Integer",
          "at " + getClass().getName());
    }
  }

  /** We just want to make sure that mapbinder's binding depends on the underlying multibinder. */
  public void testMultibinderDependencies() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        MapBinder<Integer, String> mapBinder
            = MapBinder.newMapBinder(binder(), Integer.class, String.class);
        mapBinder.addBinding(1).toInstance("A");
        mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b")));

        bindConstant().annotatedWith(Names.named("b")).to("B");
      }
    });

    Binding<Map<Integer, String>> binding = injector.getBinding(new Key<Map<Integer, String>>() {});
    HasDependencies withDependencies = (HasDependencies) binding;
    Key<?> setKey = new Key<Set<Map.Entry<Integer, Provider<String>>>>() {};
    assertEquals(ImmutableSet.<Dependency<?>>of(Dependency.get(setKey)),
        withDependencies.getDependencies());
    Set<String> elements = Sets.newHashSet();
    elements.addAll(recurseForDependencies(injector, withDependencies));
    assertEquals(ImmutableSet.of("A", "B"), elements);
  }

  private Set<String> recurseForDependencies(Injector injector, HasDependencies hasDependencies) {
    Set<String> elements = Sets.newHashSet();
    for (Dependency<?> dependency : hasDependencies.getDependencies()) {
      Binding<?> binding = injector.getBinding(dependency.getKey());
      HasDependencies deps = (HasDependencies) binding;
      if (binding instanceof InstanceBinding) {
        elements.add((String) ((InstanceBinding<?>) binding).getInstance());
      } else {
        elements.addAll(recurseForDependencies(injector, deps));
      }
    }    
    return elements;
  }

  /** We just want to make sure that mapbinder's binding depends on the underlying multibinder. */
  public void testMultibinderDependenciesInToolStage() {
    Injector injector = Guice.createInjector(Stage.TOOL, new AbstractModule() {
      @Override protected void configure() {
          MapBinder<Integer, String> mapBinder
              = MapBinder.newMapBinder(binder(), Integer.class, String.class);
          mapBinder.addBinding(1).toInstance("A");
          mapBinder.addBinding(2).to(Key.get(String.class, Names.named("b")));
  
          bindConstant().annotatedWith(Names.named("b")).to("B");
        }});

    Binding<Map<Integer, String>> binding = injector.getBinding(new Key<Map<Integer, String>>() {});
    HasDependencies withDependencies = (HasDependencies) binding;
    Key<?> setKey = new Key<Set<Map.Entry<Integer, Provider<String>>>>() {};
    assertEquals(ImmutableSet.<Dependency<?>>of(Dependency.get(setKey)),
        withDependencies.getDependencies());
  }
  

  /**
   * Our implementation maintains order, but doesn't guarantee it in the API spec.
   * TODO: specify the iteration order?
   */
  public void testBindOrderEqualsIterationOrder() {
    Injector injector = Guice.createInjector(
        new AbstractModule() {
          @Override protected void configure() {
            MapBinder<String, String> mapBinder
                = MapBinder.newMapBinder(binder(), String.class, String.class);
            mapBinder.addBinding("leonardo").toInstance("blue");
            mapBinder.addBinding("donatello").toInstance("purple");
            install(new AbstractModule() {
              @Override protected void configure() {
                MapBinder.newMapBinder(binder(), String.class, String.class)
                    .addBinding("michaelangelo").toInstance("orange");
              }
            });
          }
        },
        new AbstractModule() {
          @Override protected void configure() {
            MapBinder.newMapBinder(binder(), String.class, String.class)
                .addBinding("raphael").toInstance("red");
          }
        });

    Map<String, String> map = injector.getInstance(new Key<Map<String, String>>() {});
    Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
    assertEquals(Maps.immutableEntry("leonardo", "blue"), iterator.next());
    assertEquals(Maps.immutableEntry("donatello", "purple"), iterator.next());
    assertEquals(Maps.immutableEntry("michaelangelo", "orange"), iterator.next());
    assertEquals(Maps.immutableEntry("raphael", "red"), iterator.next());
  }
  
  /**
   * With overrides, we should get the union of all map bindings.
   */
  public void testModuleOverrideAndMapBindings() {
    Module ab = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("b").toInstance("B");
      }
    };
    Module cd = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
        multibinder.addBinding("c").toInstance("C");
        multibinder.addBinding("d").toInstance("D");
      }
    };
    Module ef = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
        multibinder.addBinding("e").toInstance("E");
        multibinder.addBinding("f").toInstance("F");
      }
    };

    Module abcd = Modules.override(ab).with(cd);
    Injector injector = Guice.createInjector(abcd, ef);
    assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"),
        injector.getInstance(Key.get(mapOfString)));
    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abcd, ef), BOTH, false, 0,
        instance("a", "A"), instance("b", "B"), instance("c", "C"), instance("d", "D"), instance(
            "e", "E"), instance("f", "F"));
  }
  
  public void testDeduplicateMapBindings() {
    Module module = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> mapbinder =
            MapBinder.newMapBinder(binder(), String.class, String.class);
        mapbinder.addBinding("a").toInstance("A");
        mapbinder.addBinding("a").toInstance("A");
        mapbinder.addBinding("b").toInstance("B");
        mapbinder.addBinding("b").toInstance("B");
        
      }
    };
    Injector injector = Guice.createInjector(module);
    assertEquals(mapOf("a", "A", "b", "B"),
        injector.getInstance(Key.get(mapOfString)));
    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(module), BOTH, false, 0,
        instance("a", "A"), instance("b", "B"));
  }
  
  /**
   * With overrides, we should get the union of all map bindings.
   */
  public void testModuleOverrideAndMapBindingsWithPermitDuplicates() {
    Module abc = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("b").toInstance("B");
        multibinder.addBinding("c").toInstance("C");
        multibinder.permitDuplicates();
      }
    };
    Module cd = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
        multibinder.addBinding("c").toInstance("C");
        multibinder.addBinding("d").toInstance("D");
        multibinder.permitDuplicates();
      }
    };
    Module ef = new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> multibinder = MapBinder.newMapBinder(binder(), String.class, String.class);
        multibinder.addBinding("e").toInstance("E");
        multibinder.addBinding("f").toInstance("F");
        multibinder.permitDuplicates();
      }
    };

    Module abcd = Modules.override(abc).with(cd);
    Injector injector = Guice.createInjector(abcd, ef);
    assertEquals(mapOf("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F"),
        injector.getInstance(Key.get(mapOfString)));
    assertMapVisitor(Key.get(mapOfString), stringType, stringType, setOf(abcd, ef), BOTH, true, 0,
        instance("a", "A"), instance("b", "B"), instance("c", "C"), instance(
            "d", "D"), instance("e", "E"), instance("f", "F"));

  }  

  /** Ensure there are no initialization race conditions in basic map injection. */
  public void testBasicMapDependencyInjection() {
    final AtomicReference<Map<String, String>> injectedMap =
        new AtomicReference<Map<String, String>>();
    final Object anObject = new Object() {
      @Inject void initialize(Map<String, String> map) {
        injectedMap.set(map);
      }
    };
    Module abc = new AbstractModule() {
      @Override protected void configure() {
        requestInjection(anObject);
        MapBinder<String, String> multibinder =
            MapBinder.newMapBinder(binder(), String.class, String.class);
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("b").toInstance("B");
        multibinder.addBinding("c").toInstance("C");
      }
    };
    Guice.createInjector(abc);
    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), injectedMap.get());
  } 

  /** Ensure there are no initialization race conditions in provider multimap injection. */
  public void testProviderMultimapDependencyInjection() {
    final AtomicReference<Map<String, Set<Provider<String>>>> injectedMultimap =
        new AtomicReference<Map<String, Set<Provider<String>>>>();
    final Object anObject = new Object() {
      @Inject void initialize(Map<String, Set<Provider<String>>> multimap) {
        injectedMultimap.set(multimap);
      }
    };
    Module abc = new AbstractModule() {
      @Override protected void configure() {
        requestInjection(anObject);
        MapBinder<String, String> multibinder =
            MapBinder.newMapBinder(binder(), String.class, String.class);
        multibinder.permitDuplicates();
        multibinder.addBinding("a").toInstance("A");
        multibinder.addBinding("b").toInstance("B");
        multibinder.addBinding("c").toInstance("C");
      }
    };
    Guice.createInjector(abc);
    Map<String, String> map = Maps.transformValues(injectedMultimap.get(),
        new Function<Set<Provider<String>>, String>() {
          @Override public String apply(Set<Provider<String>> stringProvidersSet) {
            return Iterables.getOnlyElement(stringProvidersSet).get();
          }
        });
    assertEquals(mapOf("a", "A", "b", "B", "c", "C"), map);
  }
  
  @Retention(RUNTIME) @BindingAnnotation
  @interface Abc {}

  @Retention(RUNTIME) @BindingAnnotation
  @interface De {}

  @SuppressWarnings("unchecked")
  private <K, V> Map<K, V> mapOf(Object... elements) {
    Map<K, V> result = new HashMap<K, V>();
    for (int i = 0; i < elements.length; i += 2) {
      result.put((K)elements[i], (V)elements[i+1]);
    }
    return result;
  }

  @SuppressWarnings("unchecked")
  private <V> Set<V> setOf(V... elements) {
    return new HashSet<V>(Arrays.asList(elements));
  }

  @BindingAnnotation
  @Retention(RetentionPolicy.RUNTIME)
  @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
  private static @interface Marker {}

  @Marker
  public void testMapBinderMatching() throws Exception {
    Method m = MapBinderTest.class.getDeclaredMethod("testMapBinderMatching");
    assertNotNull(m);
    final Annotation marker = m.getAnnotation(Marker.class);
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override public void configure() {
        MapBinder<Integer, Integer> mb1 =
          MapBinder.newMapBinder(binder(), Integer.class, Integer.class, Marker.class);
        MapBinder<Integer, Integer> mb2 = 
          MapBinder.newMapBinder(binder(), Integer.class, Integer.class, marker);
        mb1.addBinding(1).toInstance(1);
        mb2.addBinding(2).toInstance(2);

        // This assures us that the two binders are equivalent, so we expect the instance added to
        // each to have been added to one set.
        assertEquals(mb1, mb2);
      }
    });
    TypeLiteral<Map<Integer, Integer>> t = new TypeLiteral<Map<Integer, Integer>>() {};
    Map<Integer, Integer> s1 = injector.getInstance(Key.get(t, Marker.class));
    Map<Integer, Integer> s2 = injector.getInstance(Key.get(t, marker));

    // This assures us that the two sets are in fact equal.  They may not be same set (as in Java
    // object identical), but we shouldn't expect that, since probably Guice creates the set each
    // time in case the elements are dependent on scope.
    assertEquals(s1, s2);

    // This ensures that MultiBinder is internally using the correct set name --
    // making sure that instances of marker annotations have the same set name as
    // MarkerAnnotation.class.
    Map<Integer, Integer> expected = new HashMap<Integer, Integer>();
    expected.put(1, 1);
    expected.put(2, 2);
    assertEquals(expected, s1);
  }

  public void testTwoMapBindersAreDistinct() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {  
        MapBinder.newMapBinder(binder(), String.class, String.class)
            .addBinding("A").toInstance("a");
        
        MapBinder.newMapBinder(binder(), Integer.class, String.class)
            .addBinding(1).toInstance("b");
      }
    });
    Collector collector = new Collector();
    Binding<Map<String, String>> map1 = injector.getBinding(Key.get(mapOfString));
    map1.acceptTargetVisitor(collector);
    assertNotNull(collector.mapbinding);
    MapBinderBinding<?> map1Binding = collector.mapbinding;
  
    Binding<Map<Integer, String>> map2 = injector.getBinding(Key.get(mapOfIntString));
    map2.acceptTargetVisitor(collector);
    assertNotNull(collector.mapbinding);
    MapBinderBinding<?> map2Binding = collector.mapbinding;
  
    List<Binding<String>> bindings = injector.findBindingsByType(stringType);
    assertEquals("should have two elements: " + bindings, 2, bindings.size());
    Binding<String> a = bindings.get(0);
    Binding<String> b = bindings.get(1);
    assertEquals("a", ((InstanceBinding<String>) a).getInstance());
    assertEquals("b", ((InstanceBinding<String>) b).getInstance());
    
    // Make sure the correct elements belong to their own sets.
    assertTrue(map1Binding.containsElement(a));
    assertFalse(map1Binding.containsElement(b));
  
    assertFalse(map2Binding.containsElement(a));
    assertTrue(map2Binding.containsElement(b));
  }

  // Tests for com.google.inject.internal.WeakKeySet not leaking memory.
  public void testWeakKeySet_integration_mapbinder() {
    Key<Map<String, String>> mapKey = Key.get(new TypeLiteral<Map<String, String>>() {});
    
    Injector parentInjector = Guice.createInjector(new AbstractModule() {
          @Override protected void configure() {
            bind(String.class).toInstance("hi");
          }
        });
    WeakKeySetUtils.assertNotBlacklisted(parentInjector, mapKey);

    Injector childInjector = parentInjector.createChildInjector(new AbstractModule() {
      @Override protected void configure() {
        MapBinder<String, String> binder =
            MapBinder.newMapBinder(binder(), String.class, String.class);
        binder.addBinding("bar").toInstance("foo");
      }
    });
    WeakReference<Injector> weakRef = new WeakReference<Injector>(childInjector);
    WeakKeySetUtils.assertBlacklisted(parentInjector, mapKey);
    
    // Clear the ref, GC, and ensure that we are no longer blacklisting.
    childInjector = null;
    
    WeakKeySetUtils.awaitClear(weakRef);
    WeakKeySetUtils.assertNotBlacklisted(parentInjector, mapKey);
  }
}
