blob: 76fb619e22c4a193be5d92e39a8d2f22cce1024e [file] [log] [blame]
/*
* Copyright 2011 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.gwt.user.client.rpc;
import com.google.gwt.event.shared.UmbrellaException;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEmptyKey;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEmptyList;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEmptySet;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEmptyValue;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEnum;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEnumMapValue;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeIdentityHashMapKey;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeIdentityHashMapValue;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeSingleton;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeMap;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeSet;
import com.google.gwt.user.client.rpc.TestSetFactory.SerializableDoublyLinkedNode;
import com.google.gwt.user.client.rpc.TestSetFactory.SerializableGraphWithCFS;
import com.google.gwt.user.client.rpc.TestSetFactory.SerializablePrivateNoArg;
import com.google.gwt.user.client.rpc.TestSetFactory.SerializableWithTwoArrays;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertSame;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
/**
* Misnamed set of static validation methods used by various collection class
* tests.
* <p>
* TODO: could add generics to require args to be of the same type
*/
public class TestSetValidator {
private static class UnassignableObject {
}
/**
* Check that an Object array has it's meta-data preserved (e.g. Array.queryId),
* to ensure proper type checking on element assignment.
*/
public static boolean checkObjectArrayElementAssignment(Object[] array,
int index, Object value) {
// first check that the requested assignment succeeds
try {
array[index] = value;
} catch (ArrayStoreException e) {
return false;
}
// next check that assignment with a bogus type throws ArrayStoreException
try {
array[index] = new UnassignableObject();
return false;
} catch (ArrayStoreException e) {
return true;
}
}
public static boolean equals(boolean[] expected, boolean[] actual) {
if (actual == null) {
return false;
}
if (expected.length != actual.length) {
return false;
}
for (int i = 0; i < expected.length; ++i) {
if (expected[i] != actual[i]) {
return false;
}
}
return true;
}
public static boolean equals(byte[] expected, byte[] actual) {
if (actual == null) {
return false;
}
if (actual.length != expected.length) {
return false;
}
for (int i = 0; i < expected.length; ++i) {
if (expected[i] != actual[i]) {
return false;
}
}
return true;
}
public static boolean equals(char[] expected, char[] actual) {
if (actual == null) {
return false;
}
if (actual.length != expected.length) {
return false;
}
for (int i = 0; i < expected.length; ++i) {
if (expected[i] != actual[i]) {
return false;
}
}
return true;
}
public static boolean equals(double[] expected, double[] actual) {
if (actual == null) {
return false;
}
if (actual.length != expected.length) {
return false;
}
for (int i = 0; i < expected.length; ++i) {
if (expected[i] != actual[i]) {
return false;
}
}
return true;
}
public static boolean equals(float[] expected, float[] actual) {
if (actual == null) {
return false;
}
if (actual.length != expected.length) {
return false;
}
for (int i = 0; i < expected.length; ++i) {
if (expected[i] != actual[i]) {
return false;
}
}
return true;
}
public static boolean equals(int[] expected, int[] actual) {
if (actual == null) {
return false;
}
if (actual.length != expected.length) {
return false;
}
for (int i = 0; i < expected.length; ++i) {
if (expected[i] != actual[i]) {
return false;
}
}
return true;
}
public static boolean equals(Iterator<?> expected, Iterator<?> actual) {
while (expected.hasNext() && actual.hasNext()) {
if (!expected.next().equals(actual.next())) {
return false;
}
}
return expected.hasNext() == actual.hasNext();
}
public static boolean equals(long[] expected, long[] actual) {
if (actual == null) {
return false;
}
if (actual.length != expected.length) {
return false;
}
for (int i = 0; i < expected.length; ++i) {
if (expected[i] != actual[i]) {
return false;
}
}
return true;
}
public static boolean equals(Object[] o1, Object[] o2) {
if (o1 == o2) {
return true;
}
if (o1 == null || o2 == null) {
return false;
}
if (o1.length != o2.length) {
return false;
}
for (int i = 0; i < o1.length; ++i) {
Object e1 = o1[i];
Object e2 = o2[i];
if (e1 == e2) {
continue;
}
if (e1 == null || e2 == null) {
return false;
}
if (!e1.equals(e2)) {
return false;
}
}
return true;
}
public static boolean equals(short[] expected, short[] actual) {
if (actual == null) {
return false;
}
if (actual.length != expected.length) {
return false;
}
for (int i = 0; i < expected.length; ++i) {
if (expected[i] != actual[i]) {
return false;
}
}
return true;
}
private static boolean equals(Throwable expected, Throwable actual) {
// If one is null, both must be null (or vice-versa)
if ((expected == null) != (actual == null)) {
return false;
}
// Only check expected for null, as we know that actual is the same.
if (actual == null) {
return false;
}
String expectedMessage = expected.getMessage();
String actualMessage = actual.getMessage();
if (!equalsWithNullCheck(expectedMessage, actualMessage)) {
return false;
}
/*
* The cause field is not serialized, so we cannot verify it.
*/
/*
* Stack traces are not comparable because they are automatically filled in when
* the exception is instantiated, with the instantiation site's stack trace.
*/
return true;
}
public static boolean isValid(ArrayList<?> list) {
if (list == null) {
return false;
}
ArrayList<?> reference = TestSetFactory.createArrayList();
if (reference.size() != list.size()) {
return false;
}
return reference.equals(list);
}
public static boolean isValid(List<MarkerTypeEmptyList> list) {
return list != null && list.size() == 0;
}
public static boolean isValid(Map<MarkerTypeEmptyKey, MarkerTypeEmptyValue> map) {
return map != null && map.size() == 0;
}
public static boolean isValid(Set<MarkerTypeEmptySet> set) {
return set != null && set.size() == 0;
}
public static boolean isValidEnumKey(
EnumMap<MarkerTypeEnum, MarkerTypeEnumMapValue> expected,
EnumMap<MarkerTypeEnum, MarkerTypeEnumMapValue> map) {
if (map == null) {
return false;
}
Set<?> entries = expected.entrySet();
Iterator<?> entryIter = entries.iterator();
while (entryIter.hasNext()) {
Entry<?, ?> entry = (Entry<?, ?>) entryIter.next();
Object value = map.get(entry.getKey());
if (value != entry.getValue()) {
if (value == null || entry.getValue() == null) {
return false;
}
if (!map.get(entry.getKey()).equals(entry.getValue())) {
return false;
}
}
}
return true;
}
public static boolean isValid(EnumMap<?, ?> expected, EnumMap<?, ?> map) {
if (map == null) {
return false;
}
Set<?> entries = expected.entrySet();
Iterator<?> entryIter = entries.iterator();
while (entryIter.hasNext()) {
Entry<?, ?> entry = (Entry<?, ?>) entryIter.next();
Object value = map.get(entry.getKey());
if (value != entry.getValue()) {
if (value == null || entry.getValue() == null) {
return false;
}
if (!map.get(entry.getKey()).equals(entry.getValue())) {
return false;
}
}
}
return true;
}
public static boolean isValid(HashMap<?, ?> expected, HashMap<?, ?> map) {
if (map == null) {
return false;
}
if (expected.size() != map.size()) {
return false;
}
Set<?> entries = expected.entrySet();
Iterator<?> entryIter = entries.iterator();
while (entryIter.hasNext()) {
Entry<?, ?> entry = (Entry<?, ?>) entryIter.next();
Object value = map.get(entry.getKey());
if (value != entry.getValue()) {
if (value == null || entry.getValue() == null) {
return false;
}
if (!map.get(entry.getKey()).equals(entry.getValue())) {
return false;
}
}
}
return true;
}
public static boolean isValid(HashSet<?> expected, HashSet<?> actual) {
if (actual == null) {
return false;
}
if (expected.size() != actual.size()) {
return false;
}
Iterator<?> entryIter = expected.iterator();
while (entryIter.hasNext()) {
Object entry = entryIter.next();
if (!actual.contains(entry)) {
return false;
}
}
return true;
}
public static boolean isValidEnumKey(
IdentityHashMap<MarkerTypeEnum, MarkerTypeIdentityHashMapValue> expected,
IdentityHashMap<MarkerTypeEnum, MarkerTypeIdentityHashMapValue> map) {
if (map == null) {
return false;
}
if (expected.size() != map.size()) {
return false;
}
Set<?> entries = expected.entrySet();
Iterator<?> entryIter = entries.iterator();
while (entryIter.hasNext()) {
Entry<?, ?> entry = (Entry<?, ?>) entryIter.next();
Object value = map.get(entry.getKey());
if (value != entry.getValue()) {
if (value == null || entry.getValue() == null) {
return false;
}
if (!map.get(entry.getKey()).equals(entry.getValue())) {
return false;
}
}
}
return true;
}
public static boolean isValid(
IdentityHashMap<MarkerTypeIdentityHashMapKey, MarkerTypeIdentityHashMapValue> expected,
IdentityHashMap<MarkerTypeIdentityHashMapKey, MarkerTypeIdentityHashMapValue> map) {
if (map == null) {
return false;
}
if (expected.size() != map.size()) {
return false;
}
Set<Entry<MarkerTypeIdentityHashMapKey, MarkerTypeIdentityHashMapValue>> mapEntries =
map.entrySet();
Set<Entry<MarkerTypeIdentityHashMapKey, MarkerTypeIdentityHashMapValue>> expectedEntries =
expected.entrySet();
/*
* An IdentityHashMap uses reference equality for keys. The maps we are
* comparing have keys from different sources, so we cannot simply use get
* to find one key in the other map. Instead we need to iterate looking for
* equality. We do not check for null keys/value; rather, catch them with
* NPEs.
*/
Iterator<Entry<MarkerTypeIdentityHashMapKey, MarkerTypeIdentityHashMapValue>> expectedIter =
expectedEntries.iterator();
while (expectedIter.hasNext()) {
Entry<MarkerTypeIdentityHashMapKey, MarkerTypeIdentityHashMapValue> expectedEntry =
expectedIter.next();
Iterator<Entry<MarkerTypeIdentityHashMapKey, MarkerTypeIdentityHashMapValue>> mapIter =
mapEntries.iterator();
boolean found = false;
while (!found && mapIter.hasNext()) {
Entry<MarkerTypeIdentityHashMapKey, MarkerTypeIdentityHashMapValue> mapEntry =
mapIter.next();
if (mapEntry.getKey().equals(expectedEntry.getKey())
&& mapEntry.getValue().equals(expectedEntry.getValue())) {
found = true;
}
}
if (!found) {
return false;
}
}
return true;
}
public static boolean isValid(LinkedHashMap<?, ?> expected,
LinkedHashMap<?, ?> map) {
if (isValid((HashMap<?, ?>) expected, (HashMap<?, ?>) map)) {
Iterator<?> expectedEntries = expected.entrySet().iterator();
Iterator<?> actualEntries = map.entrySet().iterator();
return equals(expectedEntries, actualEntries);
}
return false;
}
public static boolean isValid(LinkedHashSet<?> expected, LinkedHashSet<?> map) {
if (isValid((HashSet<?>) expected, (HashSet<?>) map)) {
Iterator<?> expectedEntries = expected.iterator();
Iterator<?> actualEntries = map.iterator();
return equals(expectedEntries, actualEntries);
}
return false;
}
public static boolean isValid(LinkedList<?> expected, LinkedList<?> actual) {
if (actual == null) {
return false;
}
Iterator<?> expectedEntries = expected.iterator();
Iterator<?> actualEntries = actual.iterator();
return equals(expectedEntries, actualEntries);
}
public static boolean isValid(SerializablePrivateNoArg actual) {
if (actual == null) {
return false;
}
return actual.getValue() == 1;
}
/**
* We want to assert that the two fields have object identity.
*/
public static boolean isValid(SerializableWithTwoArrays node) {
return node.one == node.two;
}
// also checks whether the sorting of entries is maintained or not.
public static boolean isValid(TreeMap<String, MarkerTypeTreeMap> expected,
TreeMap<String, MarkerTypeTreeMap> map) {
if (map == null) {
return false;
}
if (!equalsWithNullCheck(map.comparator(), expected.comparator())) {
return false;
}
int size = 0;
if ((size = expected.size()) != map.size()) {
return false;
}
// entrySet returns entries in the sorted order
List<Map.Entry<String, MarkerTypeTreeMap>> actualList = new ArrayList<Map.Entry<String, MarkerTypeTreeMap>>(
map.entrySet());
List<Map.Entry<String, MarkerTypeTreeMap>> expectedList = new ArrayList<Map.Entry<String, MarkerTypeTreeMap>>(
expected.entrySet());
for (int index = 0; index < size; index++) {
Entry<String, MarkerTypeTreeMap> expectedEntry = expectedList.get(index);
Entry<String, MarkerTypeTreeMap> actualEntry = actualList.get(index);
if (!equalsWithNullCheck(expectedEntry.getKey(), actualEntry.getKey())
|| !equalsWithNullCheck(expectedEntry.getValue(),
actualEntry.getValue())) {
return false;
}
}
return true;
}
// also checks whether the sorting of entries is maintained or not.
public static boolean isValid(TreeSet<MarkerTypeTreeSet> expected,
TreeSet<MarkerTypeTreeSet> set) {
if (set == null) {
return false;
}
if (!equalsWithNullCheck(set.comparator(), expected.comparator())) {
return false;
}
int size = 0;
if ((size = expected.size()) != set.size()) {
return false;
}
// entrySet returns entries in the sorted order
List<MarkerTypeTreeSet> actualList = new ArrayList<MarkerTypeTreeSet>(set);
List<MarkerTypeTreeSet> expectedList = new ArrayList<MarkerTypeTreeSet>(
expected);
for (int index = 0; index < size; index++) {
if (!equalsWithNullCheck(expectedList.get(index), actualList.get(index))) {
return false;
}
}
return true;
}
public static boolean isValid(UmbrellaException expected, UmbrellaException actual) {
if (actual == null) {
return false;
}
/*
* Throwable doesn't declare equals.
*/
if (!equals(expected, actual)) {
return false;
}
/* Check causes. */
Set<Throwable> expectedCauses = expected.getCauses();
Set<Throwable> actualCauses = actual.getCauses();
/* Size. */
if (actualCauses.size() != expectedCauses.size()) {
return false;
}
/* Null elements, and make a copy of the actualCauses set */
Iterator<Throwable> expectedIter = expectedCauses.iterator();
while (expectedIter.hasNext()) {
Throwable expectedCause = expectedIter.next();
if (expectedCause == null) {
return false;
}
}
Iterator<Throwable> actualIter = actualCauses.iterator();
while (actualIter.hasNext()) {
Throwable actualCause = actualIter.next();
if (actualCause == null) {
return false;
}
}
/*
* The elements themselves. We rely on the fact that the test sets do not
* contain duplicates of causes.
*/
expectedIter = expectedCauses.iterator();
while (expectedIter.hasNext()) {
Throwable expectedCause = expectedIter.next();
actualIter = actualCauses.iterator();
boolean found = false;
while (!found && actualIter.hasNext()) {
Throwable actualCause = actualIter.next();
if (equals(expectedCause, actualCause)) {
found = true;
}
}
if (!found) {
return false;
}
}
return true;
}
public static boolean isValid(Vector<?> expected, Vector<?> actual) {
if (actual == null) {
return false;
}
return expected.equals(actual);
}
public static boolean isValidAcyclicGraph(SerializableDoublyLinkedNode actual) {
if (actual == null) {
return false;
}
if (!actual.getData().equals("head")) {
return false;
}
SerializableDoublyLinkedNode leftChild = actual.getLeftChild();
if (leftChild == null) {
return false;
}
if (!leftChild.getData().equals("lchild")) {
return false;
}
if (leftChild.getLeftChild() != null || leftChild.getRightChild() != null) {
return false;
}
SerializableDoublyLinkedNode rightChild = actual.getRightChild();
if (rightChild == null) {
return false;
}
if (!rightChild.getData().equals("rchild")) {
return false;
}
if (rightChild.getLeftChild() != null || rightChild.getRightChild() != null) {
return false;
}
return true;
}
public static boolean isValidArrayListVoid(ArrayList<Void> list) {
if (list.size() != 2) {
return false;
}
if (list.get(0) != null || list.get(1) != null) {
return false;
}
return true;
}
public static boolean isValidAsList(List<?> list) {
if (list == null) {
return false;
}
List<?> reference = TestSetFactory.createArraysAsList();
if (reference.size() != list.size()) {
return false;
}
return reference.equals(list);
}
public static boolean isValidComplexCyclicGraph(
SerializableDoublyLinkedNode actual) {
assertNotNull(actual);
if (actual == null) {
return false;
}
int i = 0;
SerializableDoublyLinkedNode currNode = actual;
for (; i < 5; ++i) {
assertEquals("n" + Integer.toString(i), currNode.getData());
if (!currNode.getData().equals("n" + Integer.toString(i))) {
return false;
}
SerializableDoublyLinkedNode nextNode = currNode.getRightChild();
SerializableDoublyLinkedNode prevNode = currNode.getLeftChild();
assertNotNull("next node", nextNode);
assertNotNull("prev node", prevNode);
if (nextNode == null || prevNode == null) {
return false;
}
assertSame("A", currNode, nextNode.getLeftChild());
if (nextNode.getLeftChild() != currNode) {
return false;
}
assertSame("B", currNode, prevNode.getRightChild());
if (prevNode.getRightChild() != currNode) {
return false;
}
currNode = currNode.getRightChild();
if (currNode == actual) {
break;
}
}
assertFalse("i = " + i, i >= 4);
if (i >= 4) {
return false;
}
return true;
}
public static boolean isValidComplexCyclicGraphWithCFS(
SerializableGraphWithCFS result) {
assertNotNull(result);
List<SerializableGraphWithCFS> array = result.getArray();
assertNotNull(array);
assertEquals(1, array.size());
SerializableGraphWithCFS child = array.get(0);
assertFalse(result == child);
assertSame(result, child.getParent());
return true;
}
public static boolean isValidSingletonList(List<MarkerTypeSingleton> list) {
if (list == null || list.size() != 1) {
return false;
}
Object value = list.get(0);
// Perform instanceof check in case RPC did the wrong thing
if (!(value instanceof MarkerTypeSingleton)) {
return false;
}
MarkerTypeSingleton singleton = (MarkerTypeSingleton) value;
if (!"singleton".equals(singleton.getValue())) {
return false;
}
return true;
}
public static boolean isValidTrivialCyclicGraph(
SerializableDoublyLinkedNode actual) {
if (actual == null) {
return false;
}
if (!actual.getData().equals("head")) {
return false;
}
SerializableDoublyLinkedNode lchild = actual.getLeftChild();
if (lchild == null) {
return false;
}
SerializableDoublyLinkedNode rchild = actual.getRightChild();
if (rchild == null) {
return false;
}
if (actual != lchild && actual != rchild) {
return false;
}
return true;
}
/**
* Wrap an exception in RuntimeException if necessary so it doesn't have to be
* listed in throws clauses.
*
* @param caught exception to wrap
*/
public static void rethrowException(Throwable caught) {
if (caught instanceof RuntimeException) {
throw (RuntimeException) caught;
} else {
throw new RuntimeException(caught);
}
}
private static boolean equalsWithNullCheck(Object a, Object b) {
return a == b || (a != null && a.equals(b));
}
}