// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.collect;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
import com.google.common.testing.EqualsTester;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * A test for {@link ImmutableSortedKeyListMultimap}. Started out as a copy of
 * ImmutableListMultimapTest.
 */
@RunWith(JUnit4.class)
public class ImmutableSortedKeyListMultimapTest {

  @Test
  public void builderPutAllIterable() {
    ImmutableSortedKeyListMultimap.Builder<String, Integer> builder
        = ImmutableSortedKeyListMultimap.builder();
    builder.putAll("foo", Arrays.asList(1, 2, 3));
    builder.putAll("bar", Arrays.asList(4, 5));
    builder.putAll("foo", Arrays.asList(6, 7));
    Multimap<String, Integer> multimap = builder.build();
    assertThat(multimap).valuesForKey("foo").containsExactly(1, 2, 3, 6, 7).inOrder();
    assertThat(multimap).valuesForKey("bar").containsExactly(4, 5).inOrder();
    assertThat(multimap).hasSize(7);
  }

  @Test
  public void builderPutAllVarargs() {
    ImmutableSortedKeyListMultimap.Builder<String, Integer> builder
        = ImmutableSortedKeyListMultimap.builder();
    builder.putAll("foo", 1, 2, 3);
    builder.putAll("bar", 4, 5);
    builder.putAll("foo", 6, 7);
    Multimap<String, Integer> multimap = builder.build();
    assertThat(multimap).valuesForKey("foo").containsExactly(1, 2, 3, 6, 7).inOrder();
    assertThat(multimap).valuesForKey("bar").containsExactly(4, 5).inOrder();
    assertThat(multimap).hasSize(7);
  }

  @Test
  public void builderPutAllMultimap() {
    Multimap<String, Integer> toPut = LinkedListMultimap.create();
    toPut.put("foo", 1);
    toPut.put("bar", 4);
    toPut.put("foo", 2);
    toPut.put("foo", 3);
    Multimap<String, Integer> moreToPut = LinkedListMultimap.create();
    moreToPut.put("foo", 6);
    moreToPut.put("bar", 5);
    moreToPut.put("foo", 7);
    ImmutableSortedKeyListMultimap.Builder<String, Integer> builder
        = ImmutableSortedKeyListMultimap.builder();
    builder.putAll(toPut);
    builder.putAll(moreToPut);
    Multimap<String, Integer> multimap = builder.build();
    assertThat(multimap).valuesForKey("foo").containsExactly(1, 2, 3, 6, 7).inOrder();
    assertThat(multimap).valuesForKey("bar").containsExactly(4, 5).inOrder();
    assertThat(multimap).hasSize(7);
  }

  @Test
  public void builderPutAllWithDuplicates() {
    ImmutableSortedKeyListMultimap.Builder<String, Integer> builder
        = ImmutableSortedKeyListMultimap.builder();
    builder.putAll("foo", 1, 2, 3);
    builder.putAll("bar", 4, 5);
    builder.putAll("foo", 1, 6, 7);
    ImmutableSortedKeyListMultimap<String, Integer> multimap = builder.build();
    assertThat(multimap).valuesForKey("foo").containsExactly(1, 2, 3, 1, 6, 7).inOrder();
    assertThat(multimap).valuesForKey("bar").containsExactly(4, 5).inOrder();
    assertThat(multimap).hasSize(8);
  }

  @Test
  public void builderPutWithDuplicates() {
    ImmutableSortedKeyListMultimap.Builder<String, Integer> builder
        = ImmutableSortedKeyListMultimap.builder();
    builder.putAll("foo", 1, 2, 3);
    builder.putAll("bar", 4, 5);
    builder.put("foo", 1);
    ImmutableSortedKeyListMultimap<String, Integer> multimap = builder.build();
    assertThat(multimap).valuesForKey("foo").containsExactly(1, 2, 3, 1).inOrder();
    assertThat(multimap).valuesForKey("bar").containsExactly(4, 5).inOrder();
    assertThat(multimap).hasSize(6);
  }

  @Test
  public void builderPutAllMultimapWithDuplicates() {
    Multimap<String, Integer> toPut = LinkedListMultimap.create();
    toPut.put("foo", 1);
    toPut.put("bar", 4);
    toPut.put("foo", 2);
    toPut.put("foo", 1);
    toPut.put("bar", 5);
    Multimap<String, Integer> moreToPut = LinkedListMultimap.create();
    moreToPut.put("foo", 6);
    moreToPut.put("bar", 4);
    moreToPut.put("foo", 7);
    moreToPut.put("foo", 2);
    ImmutableSortedKeyListMultimap.Builder<String, Integer> builder
        = ImmutableSortedKeyListMultimap.builder();
    builder.putAll(toPut);
    builder.putAll(moreToPut);
    Multimap<String, Integer> multimap = builder.build();
    assertThat(multimap).valuesForKey("foo").containsExactly(1, 2, 1, 6, 7, 2).inOrder();
    assertThat(multimap).valuesForKey("bar").containsExactly(4, 5, 4).inOrder();
    assertThat(multimap).hasSize(9);
  }

  @Test
  public void builderPutNullKey() {
    Multimap<String, Integer> toPut = LinkedListMultimap.create();
    toPut.put("foo", null);
    ImmutableSortedKeyListMultimap.Builder<String, Integer> builder
        = ImmutableSortedKeyListMultimap.builder();
    try {
      builder.put(null, 1);
      fail();
    } catch (NullPointerException expected) {}
    try {
      builder.putAll(null, Arrays.asList(1, 2, 3));
      fail();
    } catch (NullPointerException expected) {}
    try {
      builder.putAll(null, 1, 2, 3);
      fail();
    } catch (NullPointerException expected) {}
    try {
      builder.putAll(toPut);
      fail();
    } catch (NullPointerException expected) {}
  }

  @Test
  public void builderPutNullValue() {
    Multimap<String, Integer> toPut = LinkedListMultimap.create();
    toPut.put(null, 1);
    ImmutableSortedKeyListMultimap.Builder<String, Integer> builder
        = ImmutableSortedKeyListMultimap.builder();
    try {
      builder.put("foo", null);
      fail();
    } catch (NullPointerException expected) {}
    try {
      builder.putAll("foo", Arrays.asList(1, null, 3));
      fail();
    } catch (NullPointerException expected) {}
    try {
      builder.putAll("foo", 1, null, 3);
      fail();
    } catch (NullPointerException expected) {}
    try {
      builder.putAll(toPut);
      fail();
    } catch (NullPointerException expected) {}
  }

  @Test
  public void copyOf() {
    ListMultimap<String, Integer> input = ArrayListMultimap.create();
    input.put("foo", 1);
    input.put("bar", 2);
    input.put("foo", 3);
    Multimap<String, Integer> multimap = ImmutableSortedKeyListMultimap.copyOf(input);
    assertThat(input).isEqualTo(multimap);
    assertThat(multimap).isEqualTo(input);
  }

  @Test
  public void copyOfWithDuplicates() {
    ListMultimap<String, Integer> input = ArrayListMultimap.create();
    input.put("foo", 1);
    input.put("bar", 2);
    input.put("foo", 3);
    input.put("foo", 1);
    Multimap<String, Integer> multimap = ImmutableSortedKeyListMultimap.copyOf(input);
    assertThat(input).isEqualTo(multimap);
    assertThat(multimap).isEqualTo(input);
  }

  @Test
  public void copyOfEmpty() {
    ListMultimap<String, Integer> input = ArrayListMultimap.create();
    Multimap<String, Integer> multimap = ImmutableSortedKeyListMultimap.copyOf(input);
    assertThat(input).isEqualTo(multimap);
    assertThat(multimap).isEqualTo(input);
  }

  @Test
  public void copyOfImmutableListMultimap() {
    Multimap<String, Integer> multimap = createMultimap();
    assertThat(ImmutableSortedKeyListMultimap.copyOf(multimap)).isSameAs(multimap);
  }

  @Test
  public void copyOfNullKey() {
    ListMultimap<String, Integer> input = ArrayListMultimap.create();
    input.put(null, 1);
    try {
      ImmutableSortedKeyListMultimap.copyOf(input);
      fail();
    } catch (NullPointerException expected) {}
  }

  @Test
  public void copyOfNullValue() {
    ListMultimap<String, Integer> input = ArrayListMultimap.create();
    input.putAll("foo", Arrays.asList(1, null, 3));
    try {
      ImmutableSortedKeyListMultimap.copyOf(input);
      fail();
    } catch (NullPointerException expected) {}
  }

  @Test
  public void emptyMultimapReads() {
    Multimap<String, Integer> multimap = ImmutableSortedKeyListMultimap.of();
    assertThat(multimap).doesNotContainKey("foo");
    assertThat(multimap.containsValue(1)).isFalse();
    assertThat(multimap).doesNotContainEntry("foo", 1);
    assertThat(multimap.entries()).isEmpty();
    assertThat(multimap.equals(ArrayListMultimap.create())).isTrue();
    assertThat(multimap).valuesForKey("foo").isEqualTo(Collections.emptyList());
    assertThat(multimap.hashCode()).isEqualTo(0);
    assertThat(multimap).isEmpty();
    assertThat(multimap.keys()).isEqualTo(HashMultiset.create());
    assertThat(multimap).isEmpty();
    assertThat(multimap).isEmpty();
    assertThat(multimap).isEmpty();
    assertThat(multimap.toString()).isEqualTo("{}");
  }

  @Test
  public void emptyMultimapWrites() {
    Multimap<String, Integer> multimap = ImmutableSortedKeyListMultimap.of();
    UnmodifiableCollectionTests.assertMultimapIsUnmodifiable(
        multimap, "foo", 1);
  }

  private Multimap<String, Integer> createMultimap() {
    return ImmutableSortedKeyListMultimap.<String, Integer>builder()
        .put("foo", 1).put("bar", 2).put("foo", 3).build();
  }

  @Test
  public void multimapReads() {
    Multimap<String, Integer> multimap = createMultimap();
    assertThat(multimap).containsKey("foo");
    assertThat(multimap).doesNotContainKey("cat");
    assertThat(multimap.containsValue(1)).isTrue();
    assertThat(multimap.containsValue(5)).isFalse();
    assertThat(multimap).containsEntry("foo", 1);
    assertThat(multimap).doesNotContainEntry("cat", 1);
    assertThat(multimap).doesNotContainEntry("foo", 5);
    assertThat(multimap.entries()).isNotEmpty();
    assertThat(multimap).hasSize(3);
    assertThat(multimap).isNotEmpty();
    assertThat(multimap.toString()).isEqualTo("{bar=[2], foo=[1, 3]}");
  }

  @Test
  public void multimapWrites() {
    Multimap<String, Integer> multimap = createMultimap();
    UnmodifiableCollectionTests.assertMultimapIsUnmodifiable(
        multimap, "bar", 2);
  }

  @Test
  public void multimapEquals() {
    Multimap<String, Integer> multimap = createMultimap();
    Multimap<String, Integer> arrayListMultimap
        = ArrayListMultimap.create();
    arrayListMultimap.putAll("foo", Arrays.asList(1, 3));
    arrayListMultimap.put("bar", 2);

    new EqualsTester()
        .addEqualityGroup(multimap, createMultimap(), arrayListMultimap,
            ImmutableSortedKeyListMultimap.<String, Integer>builder()
                .put("bar", 2).put("foo", 1).put("foo", 3).build())
        .addEqualityGroup(ImmutableSortedKeyListMultimap.<String, Integer>builder()
            .put("bar", 2).put("foo", 3).put("foo", 1).build())
        .addEqualityGroup(ImmutableSortedKeyListMultimap.<String, Integer>builder()
            .put("foo", 2).put("foo", 3).put("foo", 1).build())
        .addEqualityGroup(ImmutableSortedKeyListMultimap.<String, Integer>builder()
            .put("bar", 2).put("foo", 3).build())
        .testEquals();
  }

  @Test
  public void asMap() {
    ImmutableSortedKeyListMultimap.Builder<String, Integer> builder
        = ImmutableSortedKeyListMultimap.builder();
    builder.putAll("foo", Arrays.asList(1, 2, 3));
    builder.putAll("bar", Arrays.asList(4, 5));
    Map<String, Collection<Integer>> map = builder.build().asMap();
    assertThat(map).containsEntry("foo", Arrays.asList(1, 2, 3));
    assertThat(map).containsEntry("bar", Arrays.asList(4, 5));
    assertThat(map).hasSize(2);
    assertThat(map).containsKey("foo");
    assertThat(map).containsKey("bar");
    assertThat(map).doesNotContainKey("notfoo");
  }

  @Test
  public void asMapEntries() {
    ImmutableSortedKeyListMultimap.Builder<String, Integer> builder
        = ImmutableSortedKeyListMultimap.builder();
    builder.putAll("foo", Arrays.asList(1, 2, 3));
    builder.putAll("bar", Arrays.asList(4, 5));
    Set<Map.Entry<String, Collection<Integer>>> set = builder.build().asMap().entrySet();
    Set<Map.Entry<String, Collection<Integer>>> other =
        ImmutableSet.<Map.Entry<String, Collection<Integer>>>builder()
        .add(new SimpleImmutableEntry<String, Collection<Integer>>("foo", Arrays.asList(1, 2, 3)))
        .add(new SimpleImmutableEntry<String, Collection<Integer>>("bar", Arrays.asList(4, 5)))
        .build();
    assertThat(set).isEqualTo(other);
  }
}
