/**
 * 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.awaitClear;
import static com.google.inject.Asserts.awaitFullGc;
import static com.google.inject.internal.WeakKeySetUtils.assertBlacklisted;
import static com.google.inject.internal.WeakKeySetUtils.assertInSet;
import static com.google.inject.internal.WeakKeySetUtils.assertNotBlacklisted;
import static com.google.inject.internal.WeakKeySetUtils.assertNotInSet;
import static com.google.inject.internal.WeakKeySetUtils.assertSourceNotInSet;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Scope;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.ModuleAnnotatedMethodScannerBinding;
import com.google.inject.spi.ProvisionListenerBinding;
import com.google.inject.spi.ScopeBinding;
import com.google.inject.spi.TypeConverterBinding;
import com.google.inject.spi.TypeListenerBinding;

import junit.framework.TestCase;

import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Tests for {@link WeakKeySet}.
 * <p>
 * Multibinding specific tests can be found in MultibinderTest and MapBinderTest.
 * 
 * @author dweis@google.com (Daniel Weis)
 */
public class WeakKeySetTest extends TestCase {

  private WeakKeySet set;

  @Override
  protected void setUp() throws Exception {
    set = new WeakKeySet(new Object());
  }

  public void testEviction() {
    TestState state = new TestState();
    Key<Integer> key = Key.get(Integer.class);
    Object source = new Object();
    
    WeakReference<Key<Integer>> weakKeyRef = new WeakReference<Key<Integer>>(key);

    set.add(key, state, source);
    assertInSet(set, key, 1, source);

    state = null;

    awaitFullGc();

    assertNotInSet(set, Key.get(Integer.class));

    // Ensure there are no hanging references.
    key = null;
    awaitClear(weakKeyRef);
  }
  
  public void testEviction_nullSource() {
    TestState state = new TestState();
    Key<Integer> key = Key.get(Integer.class);
    Object source = null;
    
    WeakReference<Key<Integer>> weakKeyRef = new WeakReference<Key<Integer>>(key);

    set.add(key, state, source);
    assertInSet(set, key, 1, source);

    state = null;

    awaitFullGc();

    assertNotInSet(set, Key.get(Integer.class));

    // Ensure there are no hanging references.
    key = null;
    awaitClear(weakKeyRef);
  }

  public void testEviction_keyOverlap_2x() {
    TestState state1 = new TestState();
    TestState state2 = new TestState();
    Key<Integer> key1 = Key.get(Integer.class);
    Key<Integer> key2 = Key.get(Integer.class);
    Object source1 = new Object();
    Object source2 = new Object();

    set.add(key1, state1, source1);
    assertInSet(set, key1, 1, source1);

    set.add(key2, state2, source2);
    assertInSet(set, key2, 2, source1, source2);

    WeakReference<Key<Integer>> weakKey1Ref = new WeakReference<Key<Integer>>(key1);
    WeakReference<Key<Integer>> weakKey2Ref = new WeakReference<Key<Integer>>(key2);
    WeakReference<Object> weakSource1Ref = new WeakReference<Object>(source1);
    WeakReference<Object> weakSource2Ref = new WeakReference<Object>(source2);

    Key<Integer> key = key1 = key2 = Key.get(Integer.class);
    state1 = null;

    awaitFullGc();

    assertSourceNotInSet(set, key, source1);
    assertInSet(set, key, 1, source2);

    source1 = source2 = null;
    
    awaitClear(weakSource1Ref);
    // Key1 will be referenced as the key in the sources backingSet and won't be
    // GC'd.
    
    // Should not be GC'd until state2 goes away.
    assertNotNull(weakSource2Ref.get());

    state2 = null;

    awaitFullGc();

    assertNotInSet(set, key);

    awaitClear(weakKey2Ref);
    awaitClear(weakSource2Ref);
    // Now that the backing set is emptied, key1 is released.
    awaitClear(weakKey1Ref);
  }
  
  public void testNoEviction_keyOverlap_2x() {
    TestState state1 = new TestState();
    TestState state2 = new TestState();
    Key<Integer> key1 = Key.get(Integer.class);
    Key<Integer> key2 = Key.get(Integer.class);
    Object source1 = new Object();
    Object source2 = new Object();

    set.add(key1, state1, source1);
    assertInSet(set, key1, 1, source1);

    set.add(key2, state2, source2);
    assertInSet(set, key2, 2, source1, source2);

    WeakReference<Key<Integer>> weakKey1Ref = new WeakReference<Key<Integer>>(key1);
    WeakReference<Key<Integer>> weakKey2Ref = new WeakReference<Key<Integer>>(key2);

    Key<Integer> key = key1 = key2 = Key.get(Integer.class);

    awaitFullGc();
    assertInSet(set, key, 2, source1, source2);

    // Ensure the keys don't get GC'd when states are still referenced. key1 will be present in the
    // as the map key but key2 could be GC'd if the implementation does something wrong.
    assertNotNull(weakKey1Ref.get());
    assertNotNull(weakKey2Ref.get());
  }

  public void testEviction_keyAndSourceOverlap_null() {
    TestState state1 = new TestState();
    TestState state2 = new TestState();
    Key<Integer> key1 = Key.get(Integer.class);
    Key<Integer> key2 = Key.get(Integer.class);
    Object source = null;

    set.add(key1, state1, source);
    assertInSet(set, key1, 1, source);

    set.add(key2, state2, source);
    // Same source so still only one value.
    assertInSet(set, key2, 1, source);
    assertInSet(set, key1, 1, source);

    WeakReference<Key<Integer>> weakKey1Ref = new WeakReference<Key<Integer>>(key1);
    WeakReference<Key<Integer>> weakKey2Ref = new WeakReference<Key<Integer>>(key2);
    WeakReference<Object> weakSourceRef = new WeakReference<Object>(source);

    Key<Integer> key = key1 = key2 = Key.get(Integer.class);
    state1 = null;

    awaitFullGc();
    // Should still have a single source.
    assertInSet(set, key, 1, source);

    source = null;

    awaitClear(weakSourceRef);
    // Key1 will be referenced as the key in the sources backingSet and won't be
    // GC'd.

    state2 = null;

    awaitFullGc();
    assertNotInSet(set, key);

    awaitClear(weakKey2Ref);
    awaitClear(weakSourceRef);
    // Now that the backing set is emptied, key1 is released.
    awaitClear(weakKey1Ref);
  }
  
  public void testEviction_keyAndSourceOverlap_nonNull() {
    TestState state1 = new TestState();
    TestState state2 = new TestState();
    Key<Integer> key1 = Key.get(Integer.class);
    Key<Integer> key2 = Key.get(Integer.class);
    Object source = new Object();

    set.add(key1, state1, source);
    assertInSet(set, key1, 1, source);

    set.add(key2, state2, source);
    // Same source so still only one value.
    assertInSet(set, key2, 1, source);

    WeakReference<Key<Integer>> weakKey1Ref = new WeakReference<Key<Integer>>(key1);
    WeakReference<Key<Integer>> weakKey2Ref = new WeakReference<Key<Integer>>(key2);
    WeakReference<Object> weakSourceRef = new WeakReference<Object>(source);

    Key<Integer> key = key1 = key2 = Key.get(Integer.class);
    state1 = null;

    awaitFullGc();

 // Same source so still only one value.
    assertInSet(set, key, 1, source);
    assertInSet(set, key1, 1, source);
    
    source = null;

    awaitFullGc();
    assertNotNull(weakSourceRef.get());
    // Key1 will be referenced as the key in the sources backingSet and won't be
    // GC'd.

    state2 = null;

    awaitFullGc();

    assertNotInSet(set, key);

    awaitClear(weakKey2Ref);
    awaitClear(weakSourceRef);
    // Now that the backing set is emptied, key1 is released.
    awaitClear(weakKey1Ref);
  }

  public void testEviction_keyOverlap_3x() {
    TestState state1 = new TestState();
    TestState state2 = new TestState();
    TestState state3 = new TestState();
    Key<Integer> key1 = Key.get(Integer.class);
    Key<Integer> key2 = Key.get(Integer.class);
    Key<Integer> key3 = Key.get(Integer.class);
    Object source1 = new Object();
    Object source2 = new Object();
    Object source3 = new Object();

    set.add(key1, state1, source1);
    assertInSet(set, key1, 1, source1);

    set.add(key2, state2, source2);
    assertInSet(set, key1, 2, source1, source2);

    set.add(key3, state3, source3);
    assertInSet(set, key1, 3, source1, source2, source3);

    WeakReference<Key<Integer>> weakKey1Ref = new WeakReference<Key<Integer>>(key1);
    WeakReference<Key<Integer>> weakKey2Ref = new WeakReference<Key<Integer>>(key2);
    WeakReference<Key<Integer>> weakKey3Ref = new WeakReference<Key<Integer>>(key3);
    WeakReference<Object> weakSource1Ref = new WeakReference<Object>(source1);
    WeakReference<Object> weakSource2Ref = new WeakReference<Object>(source2);
    WeakReference<Object> weakSource3Ref = new WeakReference<Object>(source3);

    Key<Integer> key = key1 = key2 = key3 = Key.get(Integer.class);
    state1 = null;

    awaitFullGc();
    assertSourceNotInSet(set, key, source1);
    assertInSet(set, key, 2, source2, source3);

    source1 = null;
    // Key1 will be referenced as the key in the sources backingSet and won't be
    // GC'd.
    awaitClear(weakSource1Ref);

    state2 = null;
    awaitFullGc();
    assertSourceNotInSet(set, key, source2);
    assertInSet(set, key, 1, source3);

    awaitClear(weakKey2Ref);
    
    source2 = null;
    awaitClear(weakSource2Ref);
    // Key1 will be referenced as the key in the sources backingSet and won't be
    // GC'd.

    state3 = null;
    awaitFullGc();
    assertNotInSet(set, key);

    awaitClear(weakKey3Ref);
    source3 = null;
    awaitClear(weakSource3Ref);
    // Now that the backing set is emptied, key1 is released.
    awaitClear(weakKey1Ref);
  }

  public void testWeakKeySet_integration() {
    Injector parentInjector = Guice.createInjector(new AbstractModule() {
          @Override protected void configure() {
            bind(Integer.class).toInstance(4);
          }
        });
    assertNotBlacklisted(parentInjector, Key.get(String.class));

    Injector childInjector = parentInjector.createChildInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("bar");
      }
    });
    WeakReference<Injector> weakRef = new WeakReference<Injector>(childInjector);
    assertBlacklisted(parentInjector, Key.get(String.class));
    
    // Clear the ref, GC, and ensure that we are no longer blacklisting.
    childInjector = null;
    awaitClear(weakRef);
    assertNotBlacklisted(parentInjector, Key.get(String.class));
  }
  
  public void testWeakKeySet_integration_multipleChildren() {
    Injector parentInjector = Guice.createInjector(new AbstractModule() {
          @Override protected void configure() {
            bind(Integer.class).toInstance(4);
          }
        });
    assertNotBlacklisted(parentInjector, Key.get(String.class));
    assertNotBlacklisted(parentInjector, Key.get(Long.class));

    Injector childInjector1 = parentInjector.createChildInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("foo");
      }
    });
    WeakReference<Injector> weakRef1 = new WeakReference<Injector>(childInjector1);
    assertBlacklisted(parentInjector, Key.get(String.class));
    assertNotBlacklisted(parentInjector, Key.get(Long.class));
    
    Injector childInjector2 = parentInjector.createChildInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(Long.class).toInstance(6L);
      }
    });
    WeakReference<Injector> weakRef2 = new WeakReference<Injector>(childInjector2);
    assertBlacklisted(parentInjector, Key.get(String.class));
    assertBlacklisted(parentInjector, Key.get(Long.class));
    
    // Clear ref1, GC, and ensure that we still blacklist.
    childInjector1 = null;
    awaitClear(weakRef1);
    assertNotBlacklisted(parentInjector, Key.get(String.class));
    assertBlacklisted(parentInjector, Key.get(Long.class));

    // Clear the ref, GC, and ensure that we are no longer blacklisting.
    childInjector2 = null;
    awaitClear(weakRef2);
    assertNotBlacklisted(parentInjector, Key.get(String.class));
    assertNotBlacklisted(parentInjector, Key.get(Long.class));
  }
  
  public void testWeakKeySet_integration_multipleChildren_overlappingKeys() {
    Injector parentInjector = Guice.createInjector(new AbstractModule() {
          @Override protected void configure() {
            bind(Integer.class).toInstance(4);
          }
        });
    assertNotBlacklisted(parentInjector, Key.get(String.class));

    Injector childInjector1 = parentInjector.createChildInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("foo");
      }
    });
    WeakReference<Injector> weakRef1 = new WeakReference<Injector>(childInjector1);
    assertBlacklisted(parentInjector, Key.get(String.class));
    
    Injector childInjector2 = parentInjector.createChildInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("bar");
      }
    });
    WeakReference<Injector> weakRef2 = new WeakReference<Injector>(childInjector2);
    assertBlacklisted(parentInjector, Key.get(String.class));
    
    // Clear ref1, GC, and ensure that we still blacklist.
    childInjector1 = null;
    awaitClear(weakRef1);
    assertBlacklisted(parentInjector, Key.get(String.class));

    // Clear the ref, GC, and ensure that we are no longer blacklisting.
    childInjector2 = null;
    awaitClear(weakRef2);
    assertNotBlacklisted(parentInjector, Key.get(String.class));
  }

  private static class TestState implements State {
    public State parent() {
      return new TestState();
    }

    public <T> BindingImpl<T> getExplicitBinding(Key<T> key) {
      return null;
    }

    public Map<Key<?>, Binding<?>> getExplicitBindingsThisLevel() {
      throw new UnsupportedOperationException();
    }

    public void putBinding(Key<?> key, BindingImpl<?> binding) {
      throw new UnsupportedOperationException();
    }

    public ScopeBinding getScopeBinding(Class<? extends Annotation> scopingAnnotation) {
      return null;
    }

    public void putScopeBinding(Class<? extends Annotation> annotationType, ScopeBinding scope) {
      throw new UnsupportedOperationException();
    }

    public void addConverter(TypeConverterBinding typeConverterBinding) {
      throw new UnsupportedOperationException();
    }

    public TypeConverterBinding getConverter(String stringValue, TypeLiteral<?> type, Errors errors,
        Object source) {
      throw new UnsupportedOperationException();
    }

    public Iterable<TypeConverterBinding> getConvertersThisLevel() {
      return ImmutableSet.of();
    }

    /*if[AOP]*/
    public void addMethodAspect(MethodAspect methodAspect) {
      throw new UnsupportedOperationException();
    }

    public ImmutableList<MethodAspect> getMethodAspects() {
      return ImmutableList.of();
    }
    /*end[AOP]*/

    public void addTypeListener(TypeListenerBinding typeListenerBinding) {
      throw new UnsupportedOperationException();
    }

    public List<TypeListenerBinding> getTypeListenerBindings() {
      return ImmutableList.of();
    }

    public void addProvisionListener(ProvisionListenerBinding provisionListenerBinding) {
      throw new UnsupportedOperationException();
    }

    public List<ProvisionListenerBinding> getProvisionListenerBindings() {
      return ImmutableList.of();
    }

    public void addScanner(ModuleAnnotatedMethodScannerBinding scanner) {
      throw new UnsupportedOperationException();
    }

    public List<ModuleAnnotatedMethodScannerBinding> getScannerBindings() {
      return ImmutableList.of();
    }

    public void blacklist(Key<?> key, State state, Object source) {
    }

    public boolean isBlacklisted(Key<?> key) {
      return true;
    }

    public Set<Object> getSourcesForBlacklistedKey(Key<?> key) {
      throw new UnsupportedOperationException();
    }

    public Object lock() {
      throw new UnsupportedOperationException();
    }

    public Object singletonCreationLock() {
      throw new UnsupportedOperationException();
    }

    public Map<Class<? extends Annotation>, Scope> getScopes() {
      return ImmutableMap.of();
    }
  }
}
