• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
equal(Object a, Object b)42   static boolean equal(Object a, Object b) {
43     return a == b || (a != null && a.equals(b));
44   }
45 
46   // Clone of Lists.newArrayList
copyToList(Iterable<? extends E> elements)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 
copyToList(E[] elements)53   public static <E> List<E> copyToList(E[] elements) {
54     return copyToList(Arrays.asList(elements));
55   }
56 
57   // Clone of Sets.newLinkedHashSet
copyToSet(Iterable<? extends E> elements)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 
copyToSet(E[] elements)64   public static <E> Set<E> copyToSet(E[] elements) {
65     return copyToSet(Arrays.asList(elements));
66   }
67 
68   // Would use Maps.immutableEntry
mapEntry(K key, V value)69   static <K, V> Entry<K, V> mapEntry(K key, V value) {
70     return Collections.singletonMap(key, value).entrySet().iterator().next();
71   }
72 
assertEqualIgnoringOrder( Iterable<?> expected, Iterable<?> actual)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 
assertContentsAnyOrder( Iterable<?> actual, Object... expected)92   public static void assertContentsAnyOrder(
93       Iterable<?> actual, Object... expected) {
94     assertEqualIgnoringOrder(Arrays.asList(expected), actual);
95   }
96 
addAll( Collection<E> addTo, Iterable<? extends E> elementsToAdd)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 
reverse(final List<T> list)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