Java程序  |  365行  |  12.53 KB

/*
 * Copyright (C) 2008 The Guava Authors
 *
 * 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.common.collect;

import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newLinkedList;
import static com.google.common.collect.testing.testers.CollectionIteratorTester.getIteratorKnownOrderRemoveSupportedMethod;
import static java.util.Arrays.asList;
import static org.junit.contrib.truth.Truth.ASSERT;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.testing.CollectionTestSuiteBuilder;
import com.google.common.collect.testing.TestStringCollectionGenerator;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.testing.NullPointerTester;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * Tests for {@link Collections2}.
 *
 * @author Chris Povirk
 * @author Jared Levy
 */
@GwtCompatible(emulated = true)
public class Collections2Test extends TestCase {
  @GwtIncompatible("suite")
  public static Test suite() {
    TestSuite suite = new TestSuite(Collections2Test.class.getSimpleName());
    suite.addTest(testsForFilter());
    suite.addTest(testsForFilterAll());
    suite.addTest(testsForFilterLinkedList());
    suite.addTest(testsForFilterNoNulls());
    suite.addTest(testsForFilterFiltered());
    suite.addTest(testsForTransform());
    suite.addTestSuite(Collections2Test.class);
    return suite;
  }

  static final Predicate<String> NOT_YYY_ZZZ = new Predicate<String>() {
      @Override
      public boolean apply(String input) {
        return !"yyy".equals(input) && !"zzz".equals(input);
      }
  };

  static final Predicate<String> LENGTH_1 = new Predicate<String>() {
    @Override
    public boolean apply(String input) {
      return input.length() == 1;
    }
  };

  static final Predicate<String> STARTS_WITH_VOWEL = new Predicate<String>() {
    @Override
    public boolean apply(String input) {
      return asList('a', 'e', 'i', 'o', 'u').contains(input.charAt(0));
    }
  };

  @GwtIncompatible("suite")
  private static Test testsForFilter() {
    return CollectionTestSuiteBuilder.using(
        new TestStringCollectionGenerator() {
          @Override public Collection<String> create(String[] elements) {
            List<String> unfiltered = newArrayList();
            unfiltered.add("yyy");
            unfiltered.addAll(asList(elements));
            unfiltered.add("zzz");
            return Collections2.filter(unfiltered, NOT_YYY_ZZZ);
          }
        })
        .named("Collections2.filter")
        .withFeatures(
            CollectionFeature.GENERAL_PURPOSE,
            CollectionFeature.ALLOWS_NULL_VALUES,
            CollectionFeature.KNOWN_ORDER,
            CollectionSize.ANY)
        .suppressing(getIteratorKnownOrderRemoveSupportedMethod())
        .createTestSuite();
  }

  @GwtIncompatible("suite")
  private static Test testsForFilterAll() {
    return CollectionTestSuiteBuilder.using(
        new TestStringCollectionGenerator() {
          @Override public Collection<String> create(String[] elements) {
            List<String> unfiltered = newArrayList();
            unfiltered.addAll(asList(elements));
            return Collections2.filter(unfiltered, NOT_YYY_ZZZ);
          }
        })
        .named("Collections2.filter")
        .withFeatures(
            CollectionFeature.GENERAL_PURPOSE,
            CollectionFeature.ALLOWS_NULL_VALUES,
            CollectionFeature.KNOWN_ORDER,
            CollectionSize.ANY)
        .suppressing(getIteratorKnownOrderRemoveSupportedMethod())
        .createTestSuite();
  }

  @GwtIncompatible("suite")
  private static Test testsForFilterLinkedList() {
    return CollectionTestSuiteBuilder.using(
        new TestStringCollectionGenerator() {
          @Override public Collection<String> create(String[] elements) {
            List<String> unfiltered = newLinkedList();
            unfiltered.add("yyy");
            unfiltered.addAll(asList(elements));
            unfiltered.add("zzz");
            return Collections2.filter(unfiltered, NOT_YYY_ZZZ);
          }
        })
        .named("Collections2.filter")
        .withFeatures(
            CollectionFeature.GENERAL_PURPOSE,
            CollectionFeature.ALLOWS_NULL_VALUES,
            CollectionFeature.KNOWN_ORDER,
            CollectionSize.ANY)
        .suppressing(getIteratorKnownOrderRemoveSupportedMethod())
        .createTestSuite();
  }

  @GwtIncompatible("suite")
  private static Test testsForFilterNoNulls() {
    return CollectionTestSuiteBuilder.using(
        new TestStringCollectionGenerator() {
          @Override public Collection<String> create(String[] elements) {
            List<String> unfiltered = newArrayList();
            unfiltered.add("yyy");
            unfiltered.addAll(ImmutableList.copyOf(elements));
            unfiltered.add("zzz");
            return Collections2.filter(unfiltered, LENGTH_1);
          }
        })
        .named("Collections2.filter, no nulls")
        .withFeatures(
            CollectionFeature.GENERAL_PURPOSE,
            CollectionFeature.ALLOWS_NULL_QUERIES,
            CollectionFeature.KNOWN_ORDER,
            CollectionSize.ANY)
        .suppressing(getIteratorKnownOrderRemoveSupportedMethod())
        .createTestSuite();
  }

  @GwtIncompatible("suite")
  private static Test testsForFilterFiltered() {
    return CollectionTestSuiteBuilder.using(
        new TestStringCollectionGenerator() {
          @Override public Collection<String> create(String[] elements) {
            List<String> unfiltered = newArrayList();
            unfiltered.add("yyy");
            unfiltered.addAll(ImmutableList.copyOf(elements));
            unfiltered.add("zzz");
            unfiltered.add("abc");
            return Collections2.filter(
                Collections2.filter(unfiltered, LENGTH_1), NOT_YYY_ZZZ);
          }
        })
        .named("Collections2.filter, filtered input")
        .withFeatures(
            CollectionFeature.GENERAL_PURPOSE,
            CollectionFeature.KNOWN_ORDER,
            CollectionFeature.ALLOWS_NULL_QUERIES,
            CollectionSize.ANY)
        .suppressing(getIteratorKnownOrderRemoveSupportedMethod())
        .createTestSuite();
  }

  public abstract static class FilterChangeTest extends TestCase {
    protected abstract <E> List<E> newList();

    public void testFilterIllegalAdd() {
      List<String> unfiltered = newList();
      Collection<String> filtered
          = Collections2.filter(unfiltered, NOT_YYY_ZZZ);
      filtered.add("a");
      filtered.add("b");
      ASSERT.that(filtered).hasContentsInOrder("a", "b");

      try {
        filtered.add("yyy");
        fail();
      } catch (IllegalArgumentException expected) {}

      try {
        filtered.addAll(asList("c", "zzz", "d"));
        fail();
      } catch (IllegalArgumentException expected) {}

      ASSERT.that(filtered).hasContentsInOrder("a", "b");
    }

    public void testFilterChangeUnfiltered() {
      List<String> unfiltered = newList();
      Collection<String> filtered
          = Collections2.filter(unfiltered, NOT_YYY_ZZZ);

      unfiltered.add("a");
      unfiltered.add("yyy");
      unfiltered.add("b");
      ASSERT.that(unfiltered).hasContentsInOrder("a", "yyy", "b");
      ASSERT.that(filtered).hasContentsInOrder("a", "b");

      unfiltered.remove("a");
      ASSERT.that(unfiltered).hasContentsInOrder("yyy", "b");
      ASSERT.that(filtered).hasContentsInOrder("b");

      unfiltered.clear();
      ASSERT.that(unfiltered).isEmpty();
      ASSERT.that(filtered).isEmpty();

      unfiltered.add("yyy");
      ASSERT.that(unfiltered).hasContentsInOrder("yyy");
      ASSERT.that(filtered).isEmpty();
      filtered.clear();
      ASSERT.that(unfiltered).hasContentsInOrder("yyy");
      ASSERT.that(filtered).isEmpty();

      unfiltered.clear();
      filtered.clear();
      ASSERT.that(unfiltered).isEmpty();
      ASSERT.that(filtered).isEmpty();

      unfiltered.add("a");
      ASSERT.that(unfiltered).hasContentsInOrder("a");
      ASSERT.that(filtered).hasContentsInOrder("a");
      filtered.clear();
      ASSERT.that(unfiltered).isEmpty();
      ASSERT.that(filtered).isEmpty();

      unfiltered.clear();
      Collections.addAll(unfiltered,
          "a", "b", "yyy", "zzz", "c", "d", "yyy", "zzz");
      ASSERT.that(unfiltered).hasContentsInOrder(
          "a", "b", "yyy", "zzz", "c", "d", "yyy", "zzz");
      ASSERT.that(filtered).hasContentsInOrder("a", "b", "c", "d");
      filtered.clear();
      ASSERT.that(unfiltered).hasContentsInOrder("yyy", "zzz", "yyy", "zzz");
      ASSERT.that(filtered).isEmpty();
    }

    public void testFilterChangeFiltered() {
      List<String> unfiltered = newList();
      Collection<String> filtered
          = Collections2.filter(unfiltered, NOT_YYY_ZZZ);

      unfiltered.add("a");
      unfiltered.add("yyy");
      filtered.add("b");
      ASSERT.that(unfiltered).hasContentsInOrder("a", "yyy", "b");
      ASSERT.that(filtered).hasContentsInOrder("a", "b");

      filtered.remove("a");
      ASSERT.that(unfiltered).hasContentsInOrder("yyy", "b");
      ASSERT.that(filtered).hasContentsInOrder("b");

      filtered.clear();
      ASSERT.that(unfiltered).hasContentsInOrder("yyy");
      ASSERT.that(filtered);
    }

    public void testFilterFiltered() {
      List<String> unfiltered = newList();
      Collection<String> filtered = Collections2.filter(
          Collections2.filter(unfiltered, LENGTH_1), STARTS_WITH_VOWEL);
      unfiltered.add("a");
      unfiltered.add("b");
      unfiltered.add("apple");
      unfiltered.add("banana");
      unfiltered.add("e");
      ASSERT.that(filtered).hasContentsInOrder("a", "e");
      ASSERT.that(unfiltered).hasContentsInOrder("a", "b", "apple", "banana", "e");

      try {
        filtered.add("d");
        fail();
      } catch (IllegalArgumentException expected) {}
      try {
        filtered.add("egg");
        fail();
      } catch (IllegalArgumentException expected) {}
      ASSERT.that(filtered).hasContentsInOrder("a", "e");
      ASSERT.that(unfiltered).hasContentsInOrder("a", "b", "apple", "banana", "e");

      filtered.clear();
      ASSERT.that(filtered).isEmpty();
      ASSERT.that(unfiltered).hasContentsInOrder("b", "apple", "banana");
    }
  }

  public static class ArrayListFilterChangeTest extends FilterChangeTest {
    @Override protected <E> List<E> newList() {
      return Lists.newArrayList();
    }
  }

  public static class LinkedListFilterChangeTest extends FilterChangeTest {
    @Override protected <E> List<E> newList() {
      return Lists.newLinkedList();
    }
  }

  private static final Function<String, String> REMOVE_FIRST_CHAR
      = new Function<String, String>() {
        @Override
        public String apply(String from) {
          return ((from == null) || "".equals(from))
              ? null : from.substring(1);
        }
      };

  @GwtIncompatible("suite")
  private static Test testsForTransform() {
    return CollectionTestSuiteBuilder.using(
        new TestStringCollectionGenerator() {
          @Override public Collection<String> create(String[] elements) {
            List<String> list = newArrayList();
            for (String element : elements) {
              list.add((element == null) ? null : "q" + element);
            }
            return Collections2.transform(list, REMOVE_FIRST_CHAR);
          }
        })
        .named("Collections2.transform")
        .withFeatures(
            CollectionFeature.REMOVE_OPERATIONS,
            CollectionFeature.ALLOWS_NULL_VALUES,
            CollectionFeature.KNOWN_ORDER,
            CollectionSize.ANY)
        .createTestSuite();
  }

  @GwtIncompatible("NullPointerTester")
  public void testNullPointerExceptions() throws Exception {
    NullPointerTester tester = new NullPointerTester();
    tester.testAllPublicStaticMethods(Collections2.class);
  }
}