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

import static com.google.inject.Asserts.assertContains;
import static com.google.inject.internal.SpiUtils.assertOptionalVisitor;
import static com.google.inject.internal.SpiUtils.instance;
import static com.google.inject.internal.SpiUtils.linked;
import static com.google.inject.internal.SpiUtils.providerInstance;
import static com.google.inject.internal.SpiUtils.providerKey;
import static com.google.inject.name.Names.named;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.inject.AbstractModule;
import com.google.inject.Asserts;
import com.google.inject.Binding;
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.Module;
import com.google.inject.Provider;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.SpiUtils.VisitType;
import com.google.inject.multibindings.OptionalBinder;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.Elements;
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 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.util.List;
import java.util.Map.Entry;
import java.util.Set;
import junit.framework.TestCase;

/** @author sameb@google.com (Sam Berlin) */
public class OptionalBinderTest extends TestCase {

  private static final boolean HAS_JAVA_OPTIONAL;
  private static final Class<?> JAVA_OPTIONAL_CLASS;
  private static final Method JAVA_OPTIONAL_OR_ELSE;

  static {
    Class<?> optional = null;
    Method orElse = null;
    try {
      optional = Class.forName("java.util.Optional");
      orElse = optional.getDeclaredMethod("orElse", Object.class);
    } catch (ClassNotFoundException ignored) {
    } catch (NoSuchMethodException ignored) {
    } catch (SecurityException ignored) {
    }
    HAS_JAVA_OPTIONAL = optional != null;
    JAVA_OPTIONAL_CLASS = optional;
    JAVA_OPTIONAL_OR_ELSE = orElse;
  }

  final Key<String> stringKey = Key.get(String.class);
  final TypeLiteral<Optional<String>> optionalOfString = new TypeLiteral<Optional<String>>() {};
  final TypeLiteral<?> javaOptionalOfString =
      HAS_JAVA_OPTIONAL ? RealOptionalBinder.javaOptionalOf(stringKey.getTypeLiteral()) : null;
  final TypeLiteral<Optional<Provider<String>>> optionalOfProviderString =
      new TypeLiteral<Optional<Provider<String>>>() {};
  final TypeLiteral<?> javaOptionalOfProviderString =
      HAS_JAVA_OPTIONAL
          ? RealOptionalBinder.javaOptionalOfProvider(stringKey.getTypeLiteral())
          : null;
  final TypeLiteral<Optional<javax.inject.Provider<String>>> optionalOfJavaxProviderString =
      new TypeLiteral<Optional<javax.inject.Provider<String>>>() {};
  final TypeLiteral<?> javaOptionalOfJavaxProviderString =
      HAS_JAVA_OPTIONAL
          ? RealOptionalBinder.javaOptionalOfJavaxProvider(stringKey.getTypeLiteral())
          : null;

  final Key<Integer> intKey = Key.get(Integer.class);
  final TypeLiteral<Optional<Integer>> optionalOfInteger = new TypeLiteral<Optional<Integer>>() {};
  final TypeLiteral<?> javaOptionalOfInteger =
      HAS_JAVA_OPTIONAL ? RealOptionalBinder.javaOptionalOf(intKey.getTypeLiteral()) : null;
  final TypeLiteral<Optional<Provider<Integer>>> optionalOfProviderInteger =
      new TypeLiteral<Optional<Provider<Integer>>>() {};
  final TypeLiteral<?> javaOptionalOfProviderInteger =
      HAS_JAVA_OPTIONAL ? RealOptionalBinder.javaOptionalOfProvider(intKey.getTypeLiteral()) : null;
  final TypeLiteral<Optional<javax.inject.Provider<Integer>>> optionalOfJavaxProviderInteger =
      new TypeLiteral<Optional<javax.inject.Provider<Integer>>>() {};
  final TypeLiteral<?> javaOptionalOfJavaxProviderInteger =
      HAS_JAVA_OPTIONAL
          ? RealOptionalBinder.javaOptionalOfJavaxProvider(intKey.getTypeLiteral())
          : null;

  final TypeLiteral<List<String>> listOfStrings = new TypeLiteral<List<String>>() {};

  public void testTypeNotBoundByDefault() {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class);
            requireBinding(new Key<Optional<String>>() {}); // the above specifies this.
            requireBinding(String.class); // but it doesn't specify this.
            binder().requireExplicitBindings(); // need to do this, otherwise String will JIT

            if (HAS_JAVA_OPTIONAL) {
              requireBinding(Key.get(javaOptionalOfString));
            }
          }
        };

    try {
      Guice.createInjector(module);
      fail();
    } catch (CreationException ce) {
      assertContains(
          ce.getMessage(),
          "1) Explicit bindings are required and java.lang.String is not explicitly bound.");
      assertEquals(1, ce.getErrorMessages().size());
    }
  }

  public void testOptionalIsAbsentByDefault() throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class);
          }
        };

    Injector injector = Guice.createInjector(module);
    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertFalse(optional.isPresent());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertFalse(optionalP.isPresent());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertFalse(optionalJxP.isPresent());

    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, null, null);

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertFalse(optional.isPresent());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertFalse(optionalP.isPresent());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertFalse(optionalJxP.isPresent());
    }
  }

  public void testUsesUserBoundValue() throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class);
          }

          @Provides
          String provideString() {
            return "foo";
          }
        };

    Injector injector = Guice.createInjector(module);
    assertEquals("foo", injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertEquals("foo", optional.get());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertEquals("foo", optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertEquals("foo", optionalJxP.get().get());

    assertOptionalVisitor(
        stringKey, setOf(module), VisitType.BOTH, 0, null, null, providerInstance("foo"));

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertEquals("foo", optional.get());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertEquals("foo", optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertEquals("foo", optionalJxP.get().get());
    }
  }

  public void testUsesUserBoundValueNullProvidersMakeAbsent() throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class);
          }

          @Provides
          String provideString() {
            return null;
          }
        };

    Injector injector = Guice.createInjector(module);
    assertEquals(null, injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertFalse(optional.isPresent());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertEquals(null, optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertEquals(null, optionalJxP.get().get());

    assertOptionalVisitor(
        stringKey, setOf(module), VisitType.BOTH, 0, null, null, providerInstance(null));

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertFalse(optional.isPresent());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertEquals(null, optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertEquals(null, optionalJxP.get().get());
    }
  }

  private static class JitBinding {
    @Inject
    JitBinding() {}
  }

  private static class DependsOnJitBinding {
    @Inject
    DependsOnJitBinding(JitBinding jitBinding) {}
  }

  // A previous version of OptionalBinder would fail to find jit dependendencies that were created
  // by other bindings
  public void testOptionalBinderDependsOnJitBinding() {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), JitBinding.class);
          }
        };

    // Everything should be absent since nothing triggered discovery of the jit binding
    Injector injector = Guice.createInjector(module);
    assertFalse(injector.getInstance(optionalKey(JitBinding.class)).isPresent());
    assertNull(injector.getExistingBinding(Key.get(JitBinding.class)));

    // in this case, because jit bindings are allowed in this injector, the DependsOnJitBinding
    // binding will get initialized and create jit bindings for its dependency. The optionalbinder
    // should then pick it up
    module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), JitBinding.class);
            bind(DependsOnJitBinding.class);
          }
        };
    injector = Guice.createInjector(module);
    assertTrue(injector.getInstance(optionalKey(JitBinding.class)).isPresent());
    assertNotNull(injector.getExistingBinding(Key.get(JitBinding.class)));

    // in this case, because the jit binding is discovered dynamically, the optionalbinder won't
    // find it.  In prior implementations of OptionalBinder this would depend on the exact
    // sequencing of the installation of OptionalBinder vs. these injection points that trigger
    // dynamic injection.  In the current implementation it will consistently not find it.
    module =
        new AbstractModule() {
          @Override
          protected void configure() {
            bind(Object.class)
                .toProvider(
                    new Provider<Object>() {
                      @Inject
                      void setter(Injector injector) {
                        injector.getInstance(JitBinding.class);
                      }

                      @Override
                      public Object get() {
                        return null;
                      }
                    });
            OptionalBinder.newOptionalBinder(binder(), JitBinding.class);
          }
        };
    injector = Guice.createInjector(module);
    assertFalse(injector.getInstance(optionalKey(JitBinding.class)).isPresent());
    assertNotNull(injector.getExistingBinding(Key.get(JitBinding.class)));
  }

  public <T> Key<Optional<T>> optionalKey(Class<T> type) {
    return Key.get(RealOptionalBinder.optionalOf(TypeLiteral.get(type)));
  }

  public void testSetDefault() throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
          }
        };
    Injector injector = Guice.createInjector(module);
    assertEquals("a", injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertTrue(optional.isPresent());
    assertEquals("a", optional.get());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertTrue(optionalP.isPresent());
    assertEquals("a", optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertTrue(optionalJxP.isPresent());
    assertEquals("a", optionalJxP.get().get());

    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), null, null);

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertTrue(optional.isPresent());
      assertEquals("a", optional.get());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertTrue(optionalP.isPresent());
      assertEquals("a", optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertTrue(optionalJxP.isPresent());
      assertEquals("a", optionalJxP.get().get());
    }
  }

  public void testSetBinding() throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("a");
          }
        };
    Injector injector = Guice.createInjector(module);
    assertEquals("a", injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertTrue(optional.isPresent());
    assertEquals("a", optional.get());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertTrue(optionalP.isPresent());
    assertEquals("a", optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertTrue(optionalJxP.isPresent());
    assertEquals("a", optionalJxP.get().get());

    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, instance("a"), null);

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertTrue(optional.isPresent());
      assertEquals("a", optional.get());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertTrue(optionalP.isPresent());
      assertEquals("a", optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertTrue(optionalJxP.isPresent());
      assertEquals("a", optionalJxP.get().get());
    }
  }

  public void testSetBindingOverridesDefault() throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder<String> optionalBinder =
                OptionalBinder.newOptionalBinder(binder(), String.class);
            optionalBinder.setDefault().toInstance("a");
            optionalBinder.setBinding().toInstance("b");
          }
        };
    Injector injector = Guice.createInjector(module);
    assertEquals("b", injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertTrue(optional.isPresent());
    assertEquals("b", optional.get());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertTrue(optionalP.isPresent());
    assertEquals("b", optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertTrue(optionalJxP.isPresent());
    assertEquals("b", optionalJxP.get().get());

    assertOptionalVisitor(
        stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), instance("b"), null);

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertTrue(optional.isPresent());
      assertEquals("b", optional.get());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertTrue(optionalP.isPresent());
      assertEquals("b", optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertTrue(optionalJxP.isPresent());
      assertEquals("b", optionalJxP.get().get());
    }
  }

  public void testSpreadAcrossModules() throws Exception {
    Module module1 =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class);
          }
        };
    Module module2 =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
          }
        };
    Module module3 =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b");
          }
        };

    Injector injector = Guice.createInjector(module1, module2, module3);
    assertEquals("b", injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertTrue(optional.isPresent());
    assertEquals("b", optional.get());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertTrue(optionalP.isPresent());
    assertEquals("b", optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertTrue(optionalJxP.isPresent());
    assertEquals("b", optionalJxP.get().get());

    assertOptionalVisitor(
        stringKey,
        setOf(module1, module2, module3),
        VisitType.BOTH,
        0,
        instance("a"),
        instance("b"),
        null);

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertTrue(optional.isPresent());
      assertEquals("b", optional.get());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertTrue(optionalP.isPresent());
      assertEquals("b", optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertTrue(optionalJxP.isPresent());
      assertEquals("b", optionalJxP.get().get());
    }
  }

  public void testExactSameBindingCollapses_defaults() throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class)
                .setDefault()
                .toInstance(new String("a")); // using new String to ensure .equals is checked.
            OptionalBinder.newOptionalBinder(binder(), String.class)
                .setDefault()
                .toInstance(new String("a"));
          }
        };
    Injector injector = Guice.createInjector(module);
    assertEquals("a", injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertTrue(optional.isPresent());
    assertEquals("a", optional.get());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertTrue(optionalP.isPresent());
    assertEquals("a", optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertTrue(optionalJxP.isPresent());
    assertEquals("a", optionalJxP.get().get());

    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, instance("a"), null, null);

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertTrue(optional.isPresent());
      assertEquals("a", optional.get());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertTrue(optionalP.isPresent());
      assertEquals("a", optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertTrue(optionalJxP.isPresent());
      assertEquals("a", optionalJxP.get().get());
    }
  }

  public void testExactSameBindingCollapses_actual() throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class)
                .setBinding()
                .toInstance(new String("a")); // using new String to ensure .equals is checked.
            OptionalBinder.newOptionalBinder(binder(), String.class)
                .setBinding()
                .toInstance(new String("a"));
          }
        };
    Injector injector = Guice.createInjector(module);
    assertEquals("a", injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertTrue(optional.isPresent());
    assertEquals("a", optional.get());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertTrue(optionalP.isPresent());
    assertEquals("a", optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertTrue(optionalJxP.isPresent());
    assertEquals("a", optionalJxP.get().get());

    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 0, null, instance("a"), null);

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertTrue(optional.isPresent());
      assertEquals("a", optional.get());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertTrue(optionalP.isPresent());
      assertEquals("a", optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertTrue(optionalJxP.isPresent());
      assertEquals("a", optionalJxP.get().get());
    }
  }

  public void testDifferentBindingsFail_defaults() {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
            OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("b");
          }
        };
    try {
      Guice.createInjector(module);
      fail();
    } catch (CreationException ce) {
      assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size());
      assertContains(
          ce.getMessage(),
          "1) A binding to java.lang.String annotated with @"
              + RealOptionalBinder.Default.class.getName()
              + " was already configured at "
              + module.getClass().getName()
              + ".configure(",
          "at " + module.getClass().getName() + ".configure(");
    }
  }

  public void testDifferentBindingsFail_actual() {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("a");
            OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b");
          }
        };
    try {
      Guice.createInjector(module);
      fail();
    } catch (CreationException ce) {
      assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size());
      assertContains(
          ce.getMessage(),
          "1) A binding to java.lang.String annotated with @"
              + RealOptionalBinder.Actual.class.getName()
              + " was already configured at "
              + module.getClass().getName()
              + ".configure(",
          "at " + module.getClass().getName() + ".configure(");
    }
  }

  public void testDifferentBindingsFail_both() {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
            OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("b");
            OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("b");
            OptionalBinder.newOptionalBinder(binder(), String.class).setBinding().toInstance("c");
          }
        };
    try {
      Guice.createInjector(module);
      fail();
    } catch (CreationException ce) {
      assertEquals(ce.getMessage(), 2, ce.getErrorMessages().size());
      assertContains(
          ce.getMessage(),
          "1) A binding to java.lang.String annotated with @"
              + RealOptionalBinder.Default.class.getName()
              + " was already configured at "
              + module.getClass().getName()
              + ".configure(",
          "at " + module.getClass().getName() + ".configure(",
          "2) A binding to java.lang.String annotated with @"
              + RealOptionalBinder.Actual.class.getName()
              + " was already configured at "
              + module.getClass().getName()
              + ".configure(",
          "at " + module.getClass().getName() + ".configure(");
    }
  }

  public void testQualifiedAggregatesTogether() throws Exception {
    Module module1 =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo")));
          }
        };
    Module module2 =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo")))
                .setDefault()
                .toInstance("a");
          }
        };
    Module module3 =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("foo")))
                .setBinding()
                .toInstance("b");
          }
        };

    Injector injector = Guice.createInjector(module1, module2, module3);
    assertEquals("b", injector.getInstance(Key.get(String.class, Names.named("foo"))));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString, Names.named("foo")));
    assertTrue(optional.isPresent());
    assertEquals("b", optional.get());

    Optional<Provider<String>> optionalP =
        injector.getInstance(Key.get(optionalOfProviderString, Names.named("foo")));
    assertTrue(optionalP.isPresent());
    assertEquals("b", optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString, Names.named("foo")));
    assertTrue(optionalJxP.isPresent());
    assertEquals("b", optionalJxP.get().get());

    assertOptionalVisitor(
        Key.get(String.class, Names.named("foo")),
        setOf(module1, module2, module3),
        VisitType.BOTH,
        0,
        instance("a"),
        instance("b"),
        null);

    if (HAS_JAVA_OPTIONAL) {
      optional =
          toOptional(injector.getInstance(Key.get(javaOptionalOfString, Names.named("foo"))));
      assertTrue(optional.isPresent());
      assertEquals("b", optional.get());

      optionalP =
          toOptional(
              injector.getInstance(Key.get(javaOptionalOfProviderString, Names.named("foo"))));
      assertTrue(optionalP.isPresent());
      assertEquals("b", optionalP.get().get());

      optionalJxP =
          toOptional(
              injector.getInstance(Key.get(javaOptionalOfJavaxProviderString, Names.named("foo"))));
      assertTrue(optionalJxP.isPresent());
      assertEquals("b", optionalJxP.get().get());
    }
  }

  public void testMultipleDifferentOptionals() {
    final Key<String> bKey = Key.get(String.class, named("b"));
    final Key<String> cKey = Key.get(String.class, named("c"));
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
            OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault().toInstance(1);

            OptionalBinder.newOptionalBinder(binder(), bKey).setDefault().toInstance("b");
            OptionalBinder.newOptionalBinder(binder(), cKey).setDefault().toInstance("c");
          }
        };
    Injector injector = Guice.createInjector(module);
    assertEquals("a", injector.getInstance(String.class));
    assertEquals(1, injector.getInstance(Integer.class).intValue());
    assertEquals("b", injector.getInstance(bKey));
    assertEquals("c", injector.getInstance(cKey));

    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 3, instance("a"), null, null);
    assertOptionalVisitor(intKey, setOf(module), VisitType.BOTH, 3, instance(1), null, null);
    assertOptionalVisitor(bKey, setOf(module), VisitType.BOTH, 3, instance("b"), null, null);
    assertOptionalVisitor(cKey, setOf(module), VisitType.BOTH, 3, instance("c"), null, null);
  }

  public void testOptionalIsAppropriatelyLazy() throws Exception {
    Module module =
        new AbstractModule() {
          int nextValue = 1;

          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), Integer.class)
                .setDefault()
                .to(Key.get(Integer.class, Names.named("foo")));
          }

          @Provides
          @Named("foo")
          int provideInt() {
            return nextValue++;
          }
        };
    Injector injector = Guice.createInjector(module);

    Optional<Provider<Integer>> optionalP =
        injector.getInstance(Key.get(optionalOfProviderInteger));
    Optional<javax.inject.Provider<Integer>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderInteger));

    assertEquals(1, injector.getInstance(Integer.class).intValue());
    assertEquals(2, injector.getInstance(Integer.class).intValue());

    // Calling .get() on an Optional<Integer> multiple times will keep giving the same thing
    Optional<Integer> optional = injector.getInstance(Key.get(optionalOfInteger));
    assertEquals(3, optional.get().intValue());
    assertEquals(3, optional.get().intValue());
    // But getting another Optional<Integer> will give a new one.
    assertEquals(4, injector.getInstance(Key.get(optionalOfInteger)).get().intValue());

    // And the Optional<Provider> will return a provider that gives a new value each time.
    assertEquals(5, optionalP.get().get().intValue());
    assertEquals(6, optionalP.get().get().intValue());

    assertEquals(7, optionalJxP.get().get().intValue());
    assertEquals(8, optionalJxP.get().get().intValue());

    // and same rules with java.util.Optional
    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfInteger)));
      assertEquals(9, optional.get().intValue());
      assertEquals(9, optional.get().intValue());
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfInteger)));
      assertEquals(10, optional.get().intValue());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderInteger)));
      assertEquals(11, optionalP.get().get().intValue());
      assertEquals(12, optionalP.get().get().intValue());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderInteger)));
      assertEquals(13, optionalJxP.get().get().intValue());
      assertEquals(14, optionalJxP.get().get().intValue());
    }
  }

  public void testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_default()
      throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class)
                .setDefault()
                .toProvider(Providers.<String>of(null));
          }
        };
    Injector injector = Guice.createInjector(module);
    assertNull(injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertFalse(optional.isPresent());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertTrue(optionalP.isPresent());
    assertNull(optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertTrue(optionalJxP.isPresent());
    assertNull(optionalJxP.get().get());

    assertOptionalVisitor(
        stringKey,
        setOf(module),
        VisitType.BOTH,
        0,
        SpiUtils.<String>providerInstance(null),
        null,
        null);

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertFalse(optional.isPresent());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertTrue(optionalP.isPresent());
      assertNull(optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertTrue(optionalJxP.isPresent());
      assertNull(optionalJxP.get().get());
    }
  }

  public void testLinkedToNullProvidersMakeAbsentValuesAndPresentProviders_actual()
      throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class)
                .setBinding()
                .toProvider(Providers.<String>of(null));
          }
        };
    Injector injector = Guice.createInjector(module);
    assertNull(injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertFalse(optional.isPresent());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertTrue(optionalP.isPresent());
    assertNull(optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertTrue(optionalJxP.isPresent());
    assertNull(optionalJxP.get().get());

    assertOptionalVisitor(
        stringKey,
        setOf(module),
        VisitType.BOTH,
        0,
        null,
        SpiUtils.<String>providerInstance(null),
        null);

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertFalse(optional.isPresent());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertTrue(optionalP.isPresent());
      assertNull(optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertTrue(optionalJxP.isPresent());
      assertNull(optionalJxP.get().get());
    }
  }

  // TODO(sameb): Maybe change this?
  public void testLinkedToNullActualDoesntFallbackToDefault() throws Exception {
    Module module =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
            OptionalBinder.newOptionalBinder(binder(), String.class)
                .setBinding()
                .toProvider(Providers.<String>of(null));
          }
        };
    Injector injector = Guice.createInjector(module);
    assertNull(injector.getInstance(String.class));

    Optional<String> optional = injector.getInstance(Key.get(optionalOfString));
    assertFalse(optional.isPresent());

    Optional<Provider<String>> optionalP = injector.getInstance(Key.get(optionalOfProviderString));
    assertTrue(optionalP.isPresent());
    assertNull(optionalP.get().get());

    Optional<javax.inject.Provider<String>> optionalJxP =
        injector.getInstance(Key.get(optionalOfJavaxProviderString));
    assertTrue(optionalJxP.isPresent());
    assertNull(optionalP.get().get());

    assertOptionalVisitor(
        stringKey,
        setOf(module),
        VisitType.BOTH,
        0,
        instance("a"),
        SpiUtils.<String>providerInstance(null),
        null);

    if (HAS_JAVA_OPTIONAL) {
      optional = toOptional(injector.getInstance(Key.get(javaOptionalOfString)));
      assertFalse(optional.isPresent());

      optionalP = toOptional(injector.getInstance(Key.get(javaOptionalOfProviderString)));
      assertTrue(optionalP.isPresent());
      assertNull(optionalP.get().get());

      optionalJxP = toOptional(injector.getInstance(Key.get(javaOptionalOfJavaxProviderString)));
      assertTrue(optionalJxP.isPresent());
      assertNull(optionalJxP.get().get());
    }
  }

  public void testSourceLinesInException() {
    try {
      Guice.createInjector(
          new AbstractModule() {
            @Override
            protected void configure() {
              OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault();
            }
          });
      fail();
    } catch (CreationException expected) {
      assertContains(
          expected.getMessage(),
          "No implementation for java.lang.Integer",
          "at " + getClass().getName());
    }
  }

  public void testDependencies_both() {
    Injector injector =
        Guice.createInjector(
            new AbstractModule() {
              @Override
              protected void configure() {
                OptionalBinder<String> optionalbinder =
                    OptionalBinder.newOptionalBinder(binder(), String.class);
                optionalbinder.setDefault().toInstance("A");
                optionalbinder.setBinding().to(Key.get(String.class, Names.named("b")));
                bindConstant().annotatedWith(Names.named("b")).to("B");
              }
            });

    Binding<String> binding = injector.getBinding(Key.get(String.class));
    HasDependencies withDependencies = (HasDependencies) binding;
    Set<String> elements = Sets.newHashSet();
    elements.addAll(recurseForDependencies(injector, withDependencies));
    assertEquals(ImmutableSet.of("B"), elements);
  }

  public void testDependencies_actual() {
    Injector injector =
        Guice.createInjector(
            new AbstractModule() {
              @Override
              protected void configure() {
                OptionalBinder<String> optionalbinder =
                    OptionalBinder.newOptionalBinder(binder(), String.class);
                optionalbinder.setBinding().to(Key.get(String.class, Names.named("b")));
                bindConstant().annotatedWith(Names.named("b")).to("B");
              }
            });

    Binding<String> binding = injector.getBinding(Key.get(String.class));
    HasDependencies withDependencies = (HasDependencies) binding;
    Set<String> elements = Sets.newHashSet();
    elements.addAll(recurseForDependencies(injector, withDependencies));
    assertEquals(ImmutableSet.of("B"), elements);
  }

  public void testDependencies_default() {
    Injector injector =
        Guice.createInjector(
            new AbstractModule() {
              @Override
              protected void configure() {
                OptionalBinder<String> optionalbinder =
                    OptionalBinder.newOptionalBinder(binder(), String.class);
                optionalbinder.setDefault().toInstance("A");
              }
            });

    Binding<String> binding = injector.getBinding(Key.get(String.class));
    HasDependencies withDependencies = (HasDependencies) binding;
    Set<String> elements = Sets.newHashSet();
    elements.addAll(recurseForDependencies(injector, withDependencies));
    assertEquals(ImmutableSet.of("A"), elements);
  }

  @SuppressWarnings("rawtypes")
  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;
  }

  /** Doubly-installed modules should not conflict, even when one is overridden. */
  public void testModuleOverrideRepeatedInstalls_toInstance() {
    Module m =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class);
            b.setDefault().toInstance("A");
            b.setBinding().toInstance("B");
          }
        };

    assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class)));

    Injector injector = Guice.createInjector(m, Modules.override(m).with(m));
    assertEquals("B", injector.getInstance(Key.get(String.class)));

    assertOptionalVisitor(
        stringKey,
        setOf(m, Modules.override(m).with(m)),
        VisitType.BOTH,
        0,
        instance("A"),
        instance("B"),
        null);
  }

  public void testModuleOverrideRepeatedInstalls_toKey() {
    final Key<String> aKey = Key.get(String.class, Names.named("A_string"));
    final Key<String> bKey = Key.get(String.class, Names.named("B_string"));
    Module m =
        new AbstractModule() {
          @Override
          protected void configure() {
            bind(aKey).toInstance("A");
            bind(bKey).toInstance("B");

            OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class);
            b.setDefault().to(aKey);
            b.setBinding().to(bKey);
          }
        };

    assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class)));

    Injector injector = Guice.createInjector(m, Modules.override(m).with(m));
    assertEquals("B", injector.getInstance(Key.get(String.class)));

    assertOptionalVisitor(
        stringKey,
        setOf(m, Modules.override(m).with(m)),
        VisitType.BOTH,
        0,
        linked(aKey),
        linked(bKey),
        null);
  }

  public void testModuleOverrideRepeatedInstalls_toProviderInstance() {
    // Providers#of() does not redefine equals/hashCode, so use the same one both times.
    final Provider<String> aProvider = Providers.of("A");
    final Provider<String> bProvider = Providers.of("B");
    Module m =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class);
            b.setDefault().toProvider(aProvider);
            b.setBinding().toProvider(bProvider);
          }
        };

    assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class)));

    Injector injector = Guice.createInjector(m, Modules.override(m).with(m));
    assertEquals("B", injector.getInstance(Key.get(String.class)));

    assertOptionalVisitor(
        stringKey,
        setOf(m, Modules.override(m).with(m)),
        VisitType.BOTH,
        0,
        providerInstance("A"),
        providerInstance("B"),
        null);
  }

  private static class AStringProvider implements Provider<String> {
    @Override
    public String get() {
      return "A";
    }
  }

  private static class BStringProvider implements Provider<String> {
    @Override
    public String get() {
      return "B";
    }
  }

  public void testModuleOverrideRepeatedInstalls_toProviderKey() {
    Module m =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder<String> b = OptionalBinder.newOptionalBinder(binder(), String.class);
            b.setDefault().toProvider(Key.get(AStringProvider.class));
            b.setBinding().toProvider(Key.get(BStringProvider.class));
          }
        };

    assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(String.class)));

    Injector injector = Guice.createInjector(m, Modules.override(m).with(m));
    assertEquals("B", injector.getInstance(Key.get(String.class)));

    assertOptionalVisitor(
        stringKey,
        setOf(m, Modules.override(m).with(m)),
        VisitType.BOTH,
        0,
        providerKey(Key.get(AStringProvider.class)),
        providerKey(Key.get(BStringProvider.class)),
        null);
  }

  private static class StringGrabber {
    private final String string;

    @SuppressWarnings("unused") // Found by reflection
    public StringGrabber(@Named("A_string") String string) {
      this.string = string;
    }

    @SuppressWarnings("unused") // Found by reflection
    public StringGrabber(@Named("B_string") String string, int unused) {
      this.string = string;
    }

    @Override
    public int hashCode() {
      return string.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
      return (obj instanceof StringGrabber) && ((StringGrabber) obj).string.equals(string);
    }

    @Override
    public String toString() {
      return "StringGrabber(" + string + ")";
    }
  }

  public void testModuleOverrideRepeatedInstalls_toConstructor() {
    Module m =
        new AbstractModule() {
          @Override
          protected void configure() {
            Key<String> aKey = Key.get(String.class, Names.named("A_string"));
            Key<String> bKey = Key.get(String.class, Names.named("B_string"));
            bind(aKey).toInstance("A");
            bind(bKey).toInstance("B");
            bind(Integer.class).toInstance(0); // used to disambiguate constructors

            OptionalBinder<StringGrabber> b =
                OptionalBinder.newOptionalBinder(binder(), StringGrabber.class);
            try {
              b.setDefault().toConstructor(StringGrabber.class.getConstructor(String.class));
              b.setBinding()
                  .toConstructor(StringGrabber.class.getConstructor(String.class, int.class));
            } catch (NoSuchMethodException e) {
              fail("No such method: " + e.getMessage());
            }
          }
        };

    assertEquals("B", Guice.createInjector(m, m).getInstance(Key.get(StringGrabber.class)).string);

    Injector injector = Guice.createInjector(m, Modules.override(m).with(m));
    assertEquals("B", injector.getInstance(Key.get(StringGrabber.class)).string);
  }

  /**
   * Unscoped bindings should not conflict, whether they were bound with no explicit scope, or
   * explicitly bound in {@link Scopes#NO_SCOPE}.
   */
  public void testDuplicateUnscopedBindings() {
    Module m =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder<Integer> b = OptionalBinder.newOptionalBinder(binder(), Integer.class);
            b.setDefault().to(Key.get(Integer.class, named("foo")));
            b.setDefault().to(Key.get(Integer.class, named("foo"))).in(Scopes.NO_SCOPE);
            b.setBinding().to(Key.get(Integer.class, named("foo")));
            b.setBinding().to(Key.get(Integer.class, named("foo"))).in(Scopes.NO_SCOPE);
          }

          @Provides
          @Named("foo")
          int provideInt() {
            return 5;
          }
        };
    assertEquals(5, Guice.createInjector(m).getInstance(Integer.class).intValue());
  }

  /** Ensure key hash codes are fixed at injection time, not binding time. */
  public void testKeyHashCodesFixedAtInjectionTime() {
    Module m =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder<List<String>> b =
                OptionalBinder.newOptionalBinder(binder(), listOfStrings);
            List<String> list = Lists.newArrayList();
            b.setDefault().toInstance(list);
            b.setBinding().toInstance(list);
            list.add("A");
            list.add("B");
          }
        };

    Injector injector = Guice.createInjector(m);
    for (Entry<Key<?>, Binding<?>> entry : injector.getAllBindings().entrySet()) {
      Key<?> bindingKey = entry.getKey();
      Key<?> clonedKey;
      if (bindingKey.getAnnotation() != null) {
        clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotation());
      } else if (bindingKey.getAnnotationType() != null) {
        clonedKey = Key.get(bindingKey.getTypeLiteral(), bindingKey.getAnnotationType());
      } else {
        clonedKey = Key.get(bindingKey.getTypeLiteral());
      }
      assertEquals(bindingKey, clonedKey);
      assertEquals(
          "Incorrect hashcode for " + bindingKey + " -> " + entry.getValue(),
          bindingKey.hashCode(),
          clonedKey.hashCode());
    }
  }

  /** Ensure bindings do not rehash their keys once returned from {@link Elements#getElements}. */
  public void testBindingKeysFixedOnReturnFromGetElements() {
    final List<String> list = Lists.newArrayList();
    Module m =
        new AbstractModule() {
          @Override
          protected void configure() {
            OptionalBinder<List<String>> b =
                OptionalBinder.newOptionalBinder(binder(), listOfStrings);
            b.setDefault().toInstance(list);
            list.add("A");
            list.add("B");
          }
        };

    InstanceBinding<?> binding =
        Iterables.getOnlyElement(Iterables.filter(Elements.getElements(m), InstanceBinding.class));
    Key<?> keyBefore = binding.getKey();
    assertEquals(listOfStrings, keyBefore.getTypeLiteral());

    list.add("C");
    Key<?> keyAfter = binding.getKey();
    assertSame(keyBefore, keyAfter);
  }

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

  @Marker
  public void testMatchingMarkerAnnotations() throws Exception {
    Method m = OptionalBinderTest.class.getDeclaredMethod("testMatchingMarkerAnnotations");
    assertNotNull(m);
    final Annotation marker = m.getAnnotation(Marker.class);
    Injector injector =
        Guice.createInjector(
            new AbstractModule() {
              @Override
              public void configure() {
                OptionalBinder<Integer> mb1 =
                    OptionalBinder.newOptionalBinder(
                        binder(), Key.get(Integer.class, Marker.class));
                OptionalBinder<Integer> mb2 =
                    OptionalBinder.newOptionalBinder(binder(), Key.get(Integer.class, marker));
                mb1.setDefault().toInstance(1);
                mb2.setBinding().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);
              }
            });
    Integer i1 = injector.getInstance(Key.get(Integer.class, Marker.class));
    Integer i2 = injector.getInstance(Key.get(Integer.class, marker));

    // These must be identical, because the marker annotations collapsed to the same thing.
    assertSame(i1, i2);
    assertEquals(2, i2.intValue());
  }

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

    Injector childInjector =
        parentInjector.createChildInjector(
            new AbstractModule() {
              @Override
              protected void configure() {
                OptionalBinder.newOptionalBinder(binder(), Integer.class)
                    .setDefault()
                    .toInstance(4);
              }
            });
    WeakReference<Injector> weakRef = new WeakReference<>(childInjector);
    WeakKeySetUtils.assertBlacklisted(parentInjector, Key.get(Integer.class));

    // Clear the ref, GC, and ensure that we are no longer blacklisting.
    childInjector = null;

    Asserts.awaitClear(weakRef);
    WeakKeySetUtils.assertNotBlacklisted(parentInjector, Key.get(Integer.class));
  }

  public void testCompareEqualsAgainstOtherAnnotation() {
    RealOptionalBinder.Actual impl1 = new RealOptionalBinder.ActualImpl("foo");
    RealOptionalBinder.Actual other1 = Dummy.class.getAnnotation(RealOptionalBinder.Actual.class);
    assertEquals(impl1, other1);

    RealOptionalBinder.Default impl2 = new RealOptionalBinder.DefaultImpl("foo");
    RealOptionalBinder.Default other2 = Dummy.class.getAnnotation(RealOptionalBinder.Default.class);
    assertEquals(impl2, other2);

    assertFalse(impl1.equals(impl2));
    assertFalse(impl1.equals(other2));
    assertFalse(impl2.equals(other1));
    assertFalse(other1.equals(other2));
  }

  @RealOptionalBinder.Actual("foo")
  @RealOptionalBinder.Default("foo")
  static class Dummy {}

  @SuppressWarnings("unchecked")
  private <V> Set<V> setOf(V... elements) {
    return ImmutableSet.copyOf(elements);
  }

  @SuppressWarnings("unchecked")
  private <T> Optional<T> toOptional(Object object) throws Exception {
    assertTrue(
        "not a java.util.Optional: " + object.getClass(), JAVA_OPTIONAL_CLASS.isInstance(object));
    return Optional.fromNullable((T) JAVA_OPTIONAL_OR_ELSE.invoke(object, (Void) null));
  }
}
