Home | History | Annotate | Download | only in testing
      1 /*
      2  * Copyright (C) 2009 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.collect.testing;
     18 
     19 import static junit.framework.Assert.assertEquals;
     20 import static junit.framework.Assert.assertFalse;
     21 import static junit.framework.Assert.assertTrue;
     22 
     23 import junit.framework.Assert;
     24 import junit.framework.AssertionFailedError;
     25 
     26 import java.util.ArrayList;
     27 import java.util.Arrays;
     28 import java.util.Collection;
     29 import java.util.Collections;
     30 import java.util.Comparator;
     31 import java.util.Iterator;
     32 import java.util.LinkedHashSet;
     33 import java.util.List;
     34 import java.util.ListIterator;
     35 import java.util.Map;
     36 import java.util.Map.Entry;
     37 import java.util.Set;
     38 
     39 // This class is GWT compatible.
     40 public class Helpers {
     41   // Clone of Objects.equal
     42   static boolean equal(Object a, Object b) {
     43     return a == b || (a != null && a.equals(b));
     44   }
     45 
     46   // Clone of Lists.newArrayList
     47   public static <E> List<E> copyToList(Iterable<? extends E> elements) {
     48     List<E> list = new ArrayList<E>();
     49     addAll(list, elements);
     50     return list;
     51   }
     52 
     53   public static <E> List<E> copyToList(E[] elements) {
     54     return copyToList(Arrays.asList(elements));
     55   }
     56 
     57   // Clone of Sets.newLinkedHashSet
     58   public static <E> Set<E> copyToSet(Iterable<? extends E> elements) {
     59     Set<E> set = new LinkedHashSet<E>();
     60     addAll(set, elements);
     61     return set;
     62   }
     63 
     64   public static <E> Set<E> copyToSet(E[] elements) {
     65     return copyToSet(Arrays.asList(elements));
     66   }
     67 
     68   // Would use Maps.immutableEntry
     69   static <K, V> Entry<K, V> mapEntry(K key, V value) {
     70     return Collections.singletonMap(key, value).entrySet().iterator().next();
     71   }
     72 
     73   public static void assertEqualIgnoringOrder(
     74       Iterable<?> expected, Iterable<?> actual) {
     75     List<?> exp = copyToList(expected);
     76     List<?> act = copyToList(actual);
     77     String actString = act.toString();
     78 
     79     // Of course we could take pains to give the complete description of the
     80     // problem on any failure.
     81 
     82     // Yeah it's n^2.
     83     for (Object object : exp) {
     84       if (!act.remove(object)) {
     85         Assert.fail("did not contain expected element " + object + ", "
     86             + "expected = " + exp + ", actual = " + actString);
     87       }
     88     }
     89     assertTrue("unexpected elements: " + act, act.isEmpty());
     90   }
     91 
     92   public static void assertContentsAnyOrder(
     93       Iterable<?> actual, Object... expected) {
     94     assertEqualIgnoringOrder(Arrays.asList(expected), actual);
     95   }
     96 
     97   public static <E> boolean addAll(
     98       Collection<E> addTo, Iterable<? extends E> elementsToAdd) {
     99     boolean modified = false;
    100     for (E e : elementsToAdd) {
    101       modified |= addTo.add(e);
    102     }
    103     return modified;
    104   }
    105 
    106   static <T> Iterable<T> reverse(final List<T> list) {
    107     return new Iterable<T>() {
    108       @Override
    109       public Iterator<T> iterator() {
    110         final ListIterator<T> listIter = list.listIterator(list.size());
    111         return new Iterator<T>() {
    112           @Override
    113           public boolean hasNext() {
    114             return listIter.hasPrevious();
    115           }
    116           @Override
    117           public T next() {
    118             return listIter.previous();
    119           }
    120           @Override
    121           public void remove() {
    122             listIter.remove();
    123           }
    124         };
    125       }
    126     };
    127   }
    128 
    129   static <T> Iterator<T> cycle(final Iterable<T> iterable) {
    130     return new Iterator<T>() {
    131       Iterator<T> iterator = Collections.<T>emptySet().iterator();
    132       @Override
    133       public boolean hasNext() {
    134         return true;
    135       }
    136       @Override
    137       public T next() {
    138         if (!iterator.hasNext()) {
    139           iterator = iterable.iterator();
    140         }
    141         return iterator.next();
    142       }
    143       @Override
    144       public void remove() {
    145         throw new UnsupportedOperationException();
    146       }
    147     };
    148   }
    149 
    150   static <T> T get(Iterator<T> iterator, int position) {
    151     for (int i = 0; i < position; i++) {
    152       iterator.next();
    153     }
    154     return iterator.next();
    155   }
    156 
    157   static void fail(Throwable cause, Object message) {
    158     AssertionFailedError assertionFailedError =
    159         new AssertionFailedError(String.valueOf(message));
    160     assertionFailedError.initCause(cause);
    161     throw assertionFailedError;
    162   }
    163 
    164   public static <K, V> Comparator<Entry<K, V>> entryComparator(
    165       final Comparator<? super K> keyComparator) {
    166     return new Comparator<Entry<K, V>>() {
    167       @Override
    168       public int compare(Entry<K, V> a, Entry<K, V> b) {
    169         return keyComparator.compare(a.getKey(), b.getKey());
    170       }
    171     };
    172   }
    173 
    174   public static <T> void testComparator(
    175       Comparator<? super T> comparator, T... valuesInExpectedOrder) {
    176     testComparator(comparator, Arrays.asList(valuesInExpectedOrder));
    177   }
    178 
    179   public static <T> void testComparator(
    180       Comparator<? super T> comparator, List<T> valuesInExpectedOrder) {
    181     // This does an O(n^2) test of all pairs of values in both orders
    182     for (int i = 0; i < valuesInExpectedOrder.size(); i++) {
    183       T t = valuesInExpectedOrder.get(i);
    184 
    185       for (int j = 0; j < i; j++) {
    186         T lesser = valuesInExpectedOrder.get(j);
    187         assertTrue(comparator + ".compare(" + lesser + ", " + t + ")",
    188             comparator.compare(lesser, t) < 0);
    189       }
    190 
    191       assertEquals(comparator + ".compare(" + t + ", " + t + ")",
    192           0, comparator.compare(t, t));
    193 
    194       for (int j = i + 1; j < valuesInExpectedOrder.size(); j++) {
    195         T greater = valuesInExpectedOrder.get(j);
    196         assertTrue(comparator + ".compare(" + greater + ", " + t + ")",
    197             comparator.compare(greater, t) > 0);
    198       }
    199     }
    200   }
    201 
    202   public static <T extends Comparable<? super T>> void testCompareToAndEquals(
    203       List<T> valuesInExpectedOrder) {
    204     // This does an O(n^2) test of all pairs of values in both orders
    205     for (int i = 0; i < valuesInExpectedOrder.size(); i++) {
    206       T t = valuesInExpectedOrder.get(i);
    207 
    208       for (int j = 0; j < i; j++) {
    209         T lesser = valuesInExpectedOrder.get(j);
    210         assertTrue(lesser + ".compareTo(" + t + ')', lesser.compareTo(t) < 0);
    211         assertFalse(lesser.equals(t));
    212       }
    213 
    214       assertEquals(t + ".compareTo(" + t + ')', 0, t.compareTo(t));
    215       assertTrue(t.equals(t));
    216 
    217       for (int j = i + 1; j < valuesInExpectedOrder.size(); j++) {
    218         T greater = valuesInExpectedOrder.get(j);
    219         assertTrue(greater + ".compareTo(" + t + ')', greater.compareTo(t) > 0);
    220         assertFalse(greater.equals(t));
    221       }
    222     }
    223   }
    224 
    225   /**
    226    * Returns a collection that simulates concurrent modification by
    227    * having its size method return incorrect values.  This is useful
    228    * for testing methods that must treat the return value from size()
    229    * as a hint only.
    230    *
    231    * @param delta the difference between the true size of the
    232    * collection and the values returned by the size method
    233    */
    234   public static <T> Collection<T> misleadingSizeCollection(final int delta) {
    235     // It would be nice to be able to return a real concurrent
    236     // collection like ConcurrentLinkedQueue, so that e.g. concurrent
    237     // iteration would work, but that would not be GWT-compatible.
    238     return new ArrayList<T>() {
    239       @Override public int size() { return Math.max(0, super.size() + delta); }
    240     };
    241   }
    242 
    243   /**
    244    * Returns a "nefarious" map entry with the specified key and value,
    245    * meaning an entry that is suitable for testing that map entries cannot be
    246    * modified via a nefarious implementation of equals. This is used for testing
    247    * unmodifiable collections of map entries; for example, it should not be
    248    * possible to access the raw (modifiable) map entry via a nefarious equals
    249    * method.
    250    */
    251   public static <K, V> Map.Entry<K, V> nefariousMapEntry(final K key,
    252       final V value) {
    253     return new Map.Entry<K, V>() {
    254       @Override public K getKey() {
    255         return key;
    256       }
    257       @Override public V getValue() {
    258         return value;
    259       }
    260       @Override public V setValue(V value) {
    261         throw new UnsupportedOperationException();
    262       }
    263       @SuppressWarnings("unchecked")
    264       @Override public boolean equals(Object o) {
    265         if (o instanceof Map.Entry<?, ?>) {
    266           Map.Entry<K, V> e = (Map.Entry<K, V>) o;
    267           e.setValue(value); // muhahaha!
    268 
    269           return equal(this.getKey(), e.getKey())
    270               && equal(this.getValue(), e.getValue());
    271         }
    272         return false;
    273       }
    274 
    275       @Override public int hashCode() {
    276         K k = getKey();
    277         V v = getValue();
    278         return ((k == null) ?
    279             0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
    280       }
    281 
    282       /**
    283        * Returns a string representation of the form <code>{key}={value}</code>.
    284        */
    285       @Override public String toString() {
    286         return getKey() + "=" + getValue();
    287       }
    288     };
    289   }
    290 }
    291