true
- */
- private HashMaptrue if comparison involved inexact numbers */
- protected static boolean INEXACT_COMPARED = false;
-
- /** set to true if comparison of inexact numbers is expected */
- protected static boolean INEXACT_ALLOWED = false;
-
- /**
- * Constructor: For the given instance get its Class and
- * fields.
- */
- public Inspector() {
- }
-
- /**
- * Has there been a violation -- was there inexact comparison done when it
- * was not allowed?
- *
- * @return true if inexact values have been involved in the last comparison
- * and the inexact comparison was not allowed
- */
- protected boolean inexactViolation() {
- return INEXACT_COMPARED && !INEXACT_ALLOWED;
- }
-
- /**
- * - * Compare the two given objects for extensional equality. - *
- *
- * Consider inexact numbers (types double, float,
- * Double, Float) to be the same if the relative
- * difference is below TOLERANCE
- *
- * Use == for all other primitive types and their wrapper
- * classes.
- *
- * Use the String equals method to compare two objects of the
- * type String.
- *
- * Traverse over Arrays, datasets that implement
- * {@link Traversal Traversal} and datasets that implement
- * Iterableinterface.
- *
- * For datasets that implement the Map interface compare their
- * sizes, and entry sets for set equality of key-value pairs.
- *
- * For the instances of a class that implements the
- * {@link ISame ISame} interface, use its same
- * method.
- *
- * Special tests allow the user to provide the method to invoke on the given - * object with the given argument list - *
- *
- * Additionally, user may specify that a method invocation must throw a
- * given Exception with the given message.
- *
true if the two given object are the same
- */
- public boolean isSame(T obj1, T obj2) {
- this.hashmap.clear();
- INEXACT_COMPARED = false;
- return isSamePrivate(obj1, obj2);
- }
-
- /**
- * Set up the parameters for inexact test: report failure if tolerance is
- * set below 0
- *
- * @param tolerance
- * the desired tolerance for the inexact tests
- * @return false if tolerance is negative
- */
- protected boolean inexactTest(double tolerance) {
- INEXACT_COMPARED = false;
- INEXACT_ALLOWED = true;
- // check if the provided tolerance is > 0 - fail if not.
- TOLERANCE = tolerance;
- return (tolerance < 0);
- }
-
- /**
- * Set up the parameters for exact test: report failure if inexact
- * comparisons are made
- *
- * @return true
- */
- protected boolean exactTest() {
- INEXACT_COMPARED = false;
- INEXACT_ALLOWED = false;
- return true;
- }
-
- /**
- * Compare two objects that implement the Iterable interface
- *
- * @param obj1
- * an Iterable object
- * @param obj2
- * an Iterable object
- * @return true if the two given Iterableobject are the same
- */
- public boolean isSameIterable(Iterable obj1, Iterable obj2) {
- this.hashmap.clear();
- INEXACT_ALLOWED = false;
- INEXACT_COMPARED = false;
- return isSameIterablePrivate(obj1, obj2);
- }
-
- /**
- * Compare two objects that implement the Set interface
- *
- * @param obj1
- * a Set object
- * @param obj2
- * a Set object
- * @return true if the two given object represent the same set
- */
- public boolean isSameSet(Set obj1, Set obj2) {
- this.hashmap.clear();
- INEXACT_ALLOWED = false;
- INEXACT_COMPARED = false;
- return isSameSetPrivate(obj1, obj2);
- }
-
- /**
- * Compare two objects that implement the Traversal interface
- *
- * @param obj1
- * a Traversal object
- * @param obj2
- * a Traversal object
- * @return true if the two given object represent the same
- * Traversal
- */
- public boolean isSameTraversal(Traversal obj1, Traversal obj2) {
- this.hashmap.clear();
- INEXACT_ALLOWED = false;
- INEXACT_COMPARED = false;
- return isSameTraversalPrivate(obj1, obj2);
- }
-
- /* ------------ THE METHODS USED TO COMPARE TWO OBJECTS ------------- */
- /**
- *
- * Invoked by isSame method after the hashmap
- * that records seen objects has been cleared.
- *
- *
- *
- * Compare the two given objects for extensional equality.
- *
- *
- * Consider inexact numbers (types double, float,
- * Double, Float) to be the same if the relative
- * difference is below TOLERANCE
- *
- *
- * Use == for all other primitive types and their wrapper
- * classes.
- *
- *
- * Use the String equals method to compare two objects of the
- * type String.
- *
- * Compare two objects in the same class that implements the
- * Set interface by their size and by matching the elements
- * using the equals method.
- *
- *
- * Traverse over Arrays, datasets that implement
- * {@link Traversal Traversal} and datasets that implement
- * Iterableinterface.
- *
- *
- * For datasets that implement the Map interface compare their
- * sizes, and entry sets for set equality of key-value pairs.
- *
- *
- * For the instances of a class that implements the
- * {@link ISame ISame} interface, use its same
- * method.
- *
- *
- * Special tests allow the user to provide the method to invoke on the given
- * object with the given argument list
- *
- *
- * Additionally, user may specify that a method invocation must throw a
- * given Exception with the given message.
- *
- *
- * @param obj1
- * typically the actual value
- * @param obj2
- * typically the expected value
- * @return true if the two given object are the same
- */
- @SuppressWarnings("unchecked")
- private boolean isSamePrivate(T obj1, T obj2) {
-
- /** make sure both objects are not null */
- if (obj1 == null)
- return obj2 == null; // Returns true iff obj1 & obj2 are both null,
- // otherwise returns false
- if (obj2 == null)
- return false;
- if (obj1 == obj2)
- return true; // obj1 and obj2 are the same object
-
- /** handle the world teachpack colors */
- if (this.checkIColors(obj1, obj2))
- return true;
-
- Reflector r1 = new Reflector(obj1);
- Reflector r2 = new Reflector(obj2);
-
- boolean sameClass = r1.sampleClass.equals(r2.sampleClass);
-
- if (sameClass) {
- String r1Name = r1.sampleClass.getName();
- String r2Name = r2.sampleClass.getName();
-
-
- /** handle String objects separately */
- if (r1Name.equals("java.lang.String")) {
- return obj1.equals(obj2);
- }
-
- /** handle the primitive types separately */
- if (r1.sampleClass.isPrimitive()) {
- if (isDouble(r1Name))
- return isSameDouble((Double) obj1, (Double) obj2);
- else if (isFloat(r1Name))
- return isSameFloat((Float) obj1, (Float) obj2);
- else
- return (obj1.equals(obj2));
- }
-
- /** handle the wrapper types separately */
- if (isWrapperClass(r1Name)) {
- if (isDouble(r1Name))
- return isSameDouble((Double) obj1, (Double) obj2);
- else if (isFloat(r1Name))
- return isSameFloat((Float) obj1, (Float) obj2);
- else
- return (obj1.equals(obj2));
- }
-
- /** handle the Canvas class in the draw teachpack */
- if (isOurCanvas(r1Name))
- return (obj1.equals(obj2));
-
- /** handle the images in the WorldImage hierarchy */
- if (isWorldImage(r1Name))
- return obj1.equals(obj2);
+ /** the tolerance for comparison of relative difference of inexact numbers */
+ protected static double TOLERANCE = 0.001;
+
+ /** current indentation level for pretty-printing */
+ protected static String INDENT = " ";
+
+ /**
+ * a hashmap of pairs of hashcodes for two objects that are being compared:
+ * if the same pair is compared again, the loop of comparisons stops and
+ * produces true
+ */
+ private HashMap hashmap = new HashMap();
+
+ /** set to true if comparison involved inexact numbers */
+ protected static boolean INEXACT_COMPARED = false;
+
+ /** set to true if comparison of inexact numbers is expected */
+ protected static boolean INEXACT_ALLOWED = false;
+
+ /**
+ * Constructor: For the given instance get its Class and
+ * fields.
+ */
+ public Inspector() {
+ }
+
+ /**
+ * Has there been a violation -- was there inexact comparison done when it
+ * was not allowed?
+ *
+ * @return true if inexact values have been involved in the last comparison
+ * and the inexact comparison was not allowed
+ */
+ protected boolean inexactViolation() {
+ return INEXACT_COMPARED && !INEXACT_ALLOWED;
+ }
+
+ /**
+ *
+ * Compare the two given objects for extensional equality.
+ *
+ *
+ * Consider inexact numbers (types double, float,
+ * Double, Float) to be the same if the relative
+ * difference is below TOLERANCE
+ *
+ *
+ * Use == for all other primitive types and their wrapper
+ * classes.
+ *
+ *
+ * Use the String equals method to compare two objects of the
+ * type String.
+ *
+ * Traverse over Arrays, datasets that implement
+ * {@link Traversal Traversal} and datasets that implement
+ * Iterableinterface.
+ *
+ *
+ * For datasets that implement the Map interface compare their
+ * sizes, and entry sets for set equality of key-value pairs.
+ *
+ *
+ * For the instances of a class that implements the
+ * {@link ISame ISame} interface, use its same
+ * method.
+ *
+ *
+ * Special tests allow the user to provide the method to invoke on the given
+ * object with the given argument list
+ *
+ *
+ * Additionally, user may specify that a method invocation must throw a
+ * given Exception with the given message.
+ *
+ *
+ * @param
+ * the type of the objects being compared
+ * @param obj1
+ * @param obj2
+ * @return true if the two given object are the same
+ */
+ public boolean isSame(T obj1, T obj2) {
+ this.hashmap.clear();
+ INEXACT_COMPARED = false;
+ return isSamePrivate(obj1, obj2);
+ }
+
+ /**
+ * Set up the parameters for inexact test: report failure if tolerance is
+ * set below 0
+ *
+ * @param tolerance
+ * the desired tolerance for the inexact tests
+ * @return false if tolerance is negative
+ */
+ protected boolean inexactTest(double tolerance) {
+ INEXACT_COMPARED = false;
+ INEXACT_ALLOWED = true;
+ // check if the provided tolerance is > 0 - fail if not.
+ TOLERANCE = tolerance;
+ return (tolerance < 0);
+ }
+
+ /**
+ * Set up the parameters for exact test: report failure if inexact
+ * comparisons are made
+ *
+ * @return true
+ */
+ protected boolean exactTest() {
+ INEXACT_COMPARED = false;
+ INEXACT_ALLOWED = false;
+ return true;
+ }
+
+ /**
+ * Compare two objects that implement the Iterable interface
+ *
+ * @param obj1
+ * an Iterable object
+ * @param obj2
+ * an Iterable object
+ * @return true if the two given Iterableobject are the same
+ */
+ public boolean isSameIterable(Iterable obj1, Iterable obj2) {
+ this.hashmap.clear();
+ INEXACT_ALLOWED = false;
+ INEXACT_COMPARED = false;
+ return isSameIterablePrivate(obj1, obj2);
+ }
+
+ /**
+ * Compare two objects that implement the Set interface
+ *
+ * @param obj1
+ * a Set object
+ * @param obj2
+ * a Set object
+ * @return true if the two given object represent the same set
+ */
+ public boolean isSameSet(Set obj1, Set obj2) {
+ this.hashmap.clear();
+ INEXACT_ALLOWED = false;
+ INEXACT_COMPARED = false;
+ return isSameSetPrivate(obj1, obj2);
+ }
+
+ /**
+ * Compare two objects that implement the Traversal interface
+ *
+ * @param obj1
+ * a Traversal object
+ * @param obj2
+ * a Traversal object
+ * @return true if the two given object represent the same
+ * Traversal
+ */
+ public boolean isSameTraversal(Traversal obj1, Traversal obj2) {
+ this.hashmap.clear();
+ INEXACT_ALLOWED = false;
+ INEXACT_COMPARED = false;
+ return isSameTraversalPrivate(obj1, obj2);
+ }
+
+ /* ------------ THE METHODS USED TO COMPARE TWO OBJECTS ------------- */
+ /**
+ *
+ * Invoked by isSame method after the hashmap
+ * that records seen objects has been cleared.
+ *
+ *
+ *
+ * Compare the two given objects for extensional equality.
+ *
+ *
+ * Consider inexact numbers (types double, float,
+ * Double, Float) to be the same if the relative
+ * difference is below TOLERANCE
+ *
+ *
+ * Use == for all other primitive types and their wrapper
+ * classes.
+ *
+ *
+ * Use the String equals method to compare two objects of the
+ * type String.
+ *
+ * Compare two objects in the same class that implements the
+ * Set interface by their size and by matching the elements
+ * using the equals method.
+ *
+ *
+ * Traverse over Arrays, datasets that implement
+ * {@link Traversal Traversal} and datasets that implement
+ * Iterableinterface.
+ *
+ *
+ * For datasets that implement the Map interface compare their
+ * sizes, and entry sets for set equality of key-value pairs.
+ *
+ *
+ * For the instances of a class that implements the
+ * {@link ISame ISame} interface, use its same
+ * method.
+ *
+ *
+ * Special tests allow the user to provide the method to invoke on the given
+ * object with the given argument list
+ *
+ *
+ * Additionally, user may specify that a method invocation must throw a
+ * given Exception with the given message.
+ *
+ *
+ * @param obj1
+ * typically the actual value
+ * @param obj2
+ * typically the expected value
+ * @return true if the two given object are the same
+ */
+ @SuppressWarnings("unchecked")
+ private boolean isSamePrivate(T obj1, T obj2) {
+
+ /** make sure both objects are not null */
+ if (obj1 == null)
+ return obj2 == null; // Returns true iff obj1 & obj2 are both null,
+ // otherwise returns false
+ if (obj2 == null)
+ return false;
+ if (obj1 == obj2)
+ return true; // obj1 and obj2 are the same object
+
+ /** handle the world teachpack colors */
+ if (this.checkIColors(obj1, obj2))
+ return true;
+
+ Reflector r1 = new Reflector(obj1);
+ Reflector r2 = new Reflector(obj2);
+
+ boolean sameClass = r1.sampleClass.equals(r2.sampleClass);
+
+ // if (sameClass) {
+ String r1Name = r1.sampleClass.getName();
+ String r2Name = r2.sampleClass.getName();
+
+
+ /** handle String objects separately */
+ if (r1Name.equals("java.lang.String")) {
+ return obj1.equals(obj2);
+ }
+
+ /** handle the primitive types separately */
+ if (r1.sampleClass.isPrimitive()) {
+ if (! sameClass) return false;
+ if (isDouble(r1Name))
+ return isSameDouble((Double) obj1, (Double) obj2);
+ else if (isFloat(r1Name))
+ return isSameFloat((Float) obj1, (Float) obj2);
+ else
+ return (obj1.equals(obj2));
+ }
+
+ /** handle the wrapper types separately */
+ if (isWrapperClass(r1Name)) {
+ if (! sameClass) return false;
+ if (isDouble(r1Name))
+ return isSameDouble((Double) obj1, (Double) obj2);
+ else if (isFloat(r1Name))
+ return isSameFloat((Float) obj1, (Float) obj2);
+ else
+ return (obj1.equals(obj2));
+ }
+
+ /** handle the Canvas class in the draw teachpack
+ * No, on second thought let's not do that. * /
+ if (isOurCanvas(r1Name))
+ return (obj1.equals(obj2));
+
+ /** handle the images in the WorldImage hierarchy * /
+ if (isWorldImage(r1Name))
+ return obj1.equals(obj2);
- /** handle the images in the tunes package */
- if (isTunesPackage(r1Name))
- return obj1.equals(obj2);
-
-
- /**
- * Record the information about the object compared and check
- * whether the current pair has already been tested for equality, or
- * has been viewed before.
- */
- Integer i1 = System.identityHashCode(obj1);
- Integer i2 = System.identityHashCode(obj2);
- /*
- * <>
- * [Author: Sachin Venugopalan; Date: 03/03/2012]
- * System.identityHashCode(obj) is used instead of obj.hashCode() for 2
- * reasons:
- * 1. The default (Java-platform-implemented) hashcode for an
- * Object, although not guaranteed to be unique, may for all practical
- * purposes be treated as such. However, in the event that hashcode() of
- * user-defined objects is overridden such that objects that are not the
- * "same" ["same()"-ness in our Tester framework is analogous to Java's
- * definition of "equal()"] return the same hashcode [since there exists
- * no restriction in language/convention that would disallow this; e.g.
- * all objects returning hashcode 43, say, is permitted, albeit regarded
- * a bad hashing function], we do not wish to call upon the overridden
- * version of hashcode(); instead we'd like to use the value retunred by
- * the original implementation. System.identityHashCode(obj) achieves
- * this.
- * 2. Asking for the hashcode of self-referential definitions
- * using Java's in-built container objects like java.unil.Arraylist
- * (which extends AbstractList that overrides hashcode()) causes Java to
- * spawn a circular call structure that loops infinitely; it then
- * becomes the responsibility of the programmer to make sure that such a
- * structure is culled!!) Calling System.identityHashCode(obj) instead
- * avoids this complexity.
- */
+ /** handle the images in the tunes package * /
+ if (isTunesPackage(r1Name))
+ return obj1.equals(obj2);
+ */
+
+ /**
+ * Record the information about the object compared and check
+ * whether the current pair has already been tested for equality, or
+ * has been viewed before.
+ */
+ Integer i1 = System.identityHashCode(obj1);
+ Integer i2 = System.identityHashCode(obj2);
+ /*
+ * <>
+ * [Author: Sachin Venugopalan; Date: 03/03/2012]
+ * System.identityHashCode(obj) is used instead of obj.hashCode() for 2
+ * reasons:
+ * 1. The default (Java-platform-implemented) hashcode for an
+ * Object, although not guaranteed to be unique, may for all practical
+ * purposes be treated as such. However, in the event that hashcode() of
+ * user-defined objects is overridden such that objects that are not the
+ * "same" ["same()"-ness in our Tester framework is analogous to Java's
+ * definition of "equal()"] return the same hashcode [since there exists
+ * no restriction in language/convention that would disallow this; e.g.
+ * all objects returning hashcode 43, say, is permitted, albeit regarded
+ * a bad hashing function], we do not wish to call upon the overridden
+ * version of hashcode(); instead we'd like to use the value retunred by
+ * the original implementation. System.identityHashCode(obj) achieves
+ * this.
+ * 2. Asking for the hashcode of self-referential definitions
+ * using Java's in-built container objects like java.unil.Arraylist
+ * (which extends AbstractList that overrides hashcode()) causes Java to
+ * spawn a circular call structure that loops infinitely; it then
+ * becomes the responsibility of the programmer to make sure that such a
+ * structure is culled!!) Calling System.identityHashCode(obj) instead
+ * avoids this complexity.
+ */
// this code can be used for debugging:
-// if(showComparisonDetail){
-// System.out.println("Comparing:-");
-// System.out.println("\tclass 1:" + r1.sampleClass.getName()
-// + "; hashcode:" + i1);
-// System.out.println("\tclass 2:" + r2.sampleClass.getName()
-// + "; hashcode:" + i2);
-// System.out.println("\tpair-hashmap key:" + i1 * i1 + i2 * i2);
-// }
-
- Integer i2match = this.hashmap.get(i1 * i1 + i2 * i2);
- /*
- * <>
- * [Author: Sachin Venugopalan; Date: 03/03/2012]
- * In order to handle circularity, we need to keep track of pairs of
- * objects that have already been compared for equality (or for
- * which an equality check has already been initiated, and is
- * pending completion owing to a circular definition). In order to
- * look up pairs of already-seen objects efficiently, we need a
- * hash-based lookup directory such as a Hashset. The "key" (or
- * identifier) that is stored in the lookup directory should
- * identify the pair of objects; also it ought to be "symmetrical"
- * i.e. the pair of objects is not to be treated as an ordered pair
- * -- this stems from the fact that equality (rather, "sameness")
- * between two objects itself is a symmetrical relationship.
- * In other words, having seen the pair (obj1, obj2) is identical to
- * having seen the pair (obj2, obj1) We have chosen i1*i1 + i2*i2 to
- * be this symmetrical identifier of the pair of objects, where i1 &
- * i2 are their (original) hashcodes. This choice is perhaps better
- * than i1*i2, say, because such an alternate choice potentially
- * leads to more collisions. However, there is no absolute guarantee
- * of uniqueness of i1*i1 + i2*i2 (simply because there is no
- * absolute guarantee of uniqueness of i1 and i2; we simply assume
- * their uniqueness for all practical purposes, given Java's current
- * implementation of hashcodes that relates to the unique memory
- * locations at which objects reside) Hence, we perform a second
- * "validation" step to confirm the identity of the pair of objects
- * by seeing if they map to a chosen value i1+i2 (note that this is
- * again symmetric) The second validation step may not be very
- * meaningful, and for the time being, it exists more for legacy reasons.
- */
- if ((i2match != null) && (i2match.equals(i1 + i2))) {
-// if(showComparisonDetail)
-// System.out.println("\tcheck done already for this pair:" + i1
-// * i1 + i2 * i2 + " => " + i2match.toString());
- return true;
- }
- this.hashmap.put(i1 * i1 + i2 * i2, i1 + i2);
-
- /** handle Array objects */
- if (obj1.getClass().isArray() && obj2.getClass().isArray()
- && obj1.getClass() == obj2.getClass()) {
- int length = Array.getLength(obj1);
- if (Array.getLength(obj2) == length) {
- for (int i = 0; i < length; i++) {
- if (!isSame(Array.get(obj1, i), Array.get(obj2, i)))
- return false;
- }
- return true;
- } else
- return false;
- }
-
- /** handle ISame objects by delegating to the user-defined method */
- if ((obj1 instanceof ISame) && (obj2 instanceof ISame))
- return ((ISame) obj1).same((ISame) obj2);
-
- /**
- * handle the Set objects in the Java Collection library by
- * comparing their size, and data items -- here we use the equals
- * method when comparing the set elements
- */
- if ((obj1 instanceof Set) && (obj2 instanceof Set)
- && obj1.getClass().getName().startsWith("java.util"))
- return isSameSet((Set) obj1, (Set) obj2);
-
- /**
- * handle Iterable objects in the Java Collection library by
- * comparing their size, then comparing the elements pairwise
- */
- if ((obj1 instanceof Iterable) && (obj2 instanceof Iterable)
- && obj1.getClass().getName().startsWith("java.util"))
- return isSameIterablePrivate((Iterable) obj1,
- (Iterable) obj2);
-
- /**
- * handle the Map objects in the Java Collection library by
- * comparing their size, the key-set, and key-value mappings
- */
- if ((obj1 instanceof Map) && (obj2 instanceof Map)
- && obj1.getClass().getName().startsWith("java.util"))
- return isSameMap((Map) obj1, (Map) obj2);
-
- /** now handle the general case */
- boolean sameValues = true;
- int i = 0;
- try {
- for (; i < Array.getLength(r1.sampleDeclaredFields); i++) {
- sameValues = sameValues
- && isSamePrivate(
- r1.sampleDeclaredFields[i].get(obj1),
- r2.sampleDeclaredFields[i].get(obj2));
- }
- } catch (IllegalAccessException e) {
- System.out.println("same comparing "
- + r1.sampleDeclaredFields[i].getType().getName()
- + " and "
- + r2.sampleDeclaredFields[i].getType().getName()
- + "cannot access the field " + i + " message: "
- + e.getMessage());
- System.out.println("class 1: " + r1.sampleClass.getName());
- System.out.println("class 2: " + r2.sampleClass.getName());
- }
-
- return sameValues;
- } else
- return false;
- }
-
- /**
- * Determine whether the relative difference between two double numbers is
- * below the expected TOLERANCE Measure absolute tolerance, if
- * one of the numbers is exact zero.
- *
- * @param d1
- * the first inexact number
- * @param d2
- * the second inexact number
- * @return true is the two numbers are nearly the same
- */
- protected boolean isSameDouble(double d1, double d2) {
- if (d1 - d2 == 0.0)
- return true;
- else {
- INEXACT_COMPARED = true;
- if (d1 == 0.0)
- return Math.abs(d2) < TOLERANCE;
- if (d2 == 0.0)
- return Math.abs(d1) < TOLERANCE;
-
- else
- // d1, d2 are non-zero
- // return (Math.abs(d1 - d2) / (Math.max (Math.abs(d1),
- // Math.abs(d2))))
- return Math.abs(d1 - d2) / (Math.abs((d1 + d2) / 2)) < TOLERANCE;
- }
- }
-
- /**
- * Determine whether the relative difference between two float numbers is
- * below the expected TOLERANCE Measure absolute tolerance, if
- * one of the numbers is exact zero.
- *
- * @param f1
- * the first inexact number
- * @param f2
- * the second inexact number
- * @return true is the two numbers are nearly the same
- */
- protected boolean isSameFloat(float f1, float f2) {
- if (f1 - f2 == 0.0)
- return true;
- else {
- INEXACT_COMPARED = true;
- Double d1 = ((Float) f1).doubleValue();
- Double d2 = ((Float) f2).doubleValue();
-
- if (f1 == 0.0)
- return Math.abs(d2) < TOLERANCE;
- if (f2 == 0.0)
- return Math.abs(d1) < TOLERANCE;
-
- // f1, f2 are non-zero
- return (Math.abs(d1 - d2) / (Math.max(Math.abs(d1), Math.abs(d2)))) < TOLERANCE;
- }
- }
-
- /**
- * Determine whether two Iterable objects generate the same
- * data elements in the same order.
- *
- * @param obj1
- * the first Iterable dataset
- * @param obj2
- * the second Iterable dataset
- * @return true is the two datasets are extensionally equal
- */
- private boolean isSameIterablePrivate(Iterable obj1, Iterable obj2) {
- Iterator it1 = obj1.iterator();
- Iterator it2 = obj2.iterator();
-
- return this.isSameData(it1, it2);
- }
-
- /**
- * Determine whether two Traversal objects generate the same
- * data elements in the same order.
- *
- * @param obj1
- * the first Traversal dataset
- * @param obj2
- * the second Traversal dataset
- * @return true is the two datasets are extensionally equal
- */
- private boolean isSameTraversalPrivate(Traversal obj1,
- Traversal obj2) {
- Traversal it1 = obj1;
- Traversal it2 = obj2;
-
- return this.isSameTraversalData(it1, it2);
- }
-
- /**
- * Determine whether two Iterators generate the same data in
- * the same order.
- *
- * @param it1
- * the first Iterator
- * @param it2
- * the second Iterator
- * @return true is both datasets contained the same data elements (in the
- * same order)
- */
- protected boolean isSameData(Iterator it1, Iterator it2) {
- /** if the first dataset is empty, the second one has to be too */
- if (!it1.hasNext()) {
- return !it2.hasNext();
- }
- /** the first dataset is nonempty - make sure the second one is too... */
- else if (!it2.hasNext())
- return false;
- /** now both have data - compare the next pair of data and recur */
- else {
- return this.isSamePrivate(it1.next(), it2.next())
- && this.isSameData(it1, it2);
- }
- }
-
- /**
- * Determine whether two Traversals generate the same data in
- * the same order.
- *
- * @param tr1
- * the first Traversal
- * @param tr2
- * the second Traversal
- * @return true is both datasets contained the same data elements
- * (in the same order)
- */
- protected boolean isSameTraversalData(Traversal tr1, Traversal tr2) {
- /** if the first dataset is empty, the second one has to be too */
- if (tr1.isEmpty()) {
- return tr2.isEmpty();
- }
- /** the first dataset is nonempty - make sure the second one is too... */
- else if (tr2.isEmpty())
- return false;
- /** now both have data - compare the next pair of data and recur */
- else {
- return this.isSamePrivate(tr1.getFirst(), tr2.getFirst())
- && this.isSameTraversalData(tr1.getRest(), tr2.getRest());
- }
- }
-
- /**
- * Determine whether two Map objects have the same key-value
- * sets of data
- *
- * @param obj1
- * the first Map dataset
- * @param obj2
- * the second Map dataset
- * @return true if the two maps are extensionally equal
- */
- protected boolean isSameMap(Map obj1, Map obj2) {
- // make sure both maps have the same size keyset
- if (obj1.size() != obj2.size())
- return false;
-
- // the key sets for the two maps have the same size - pick one
- Set set1 = obj1.keySet();
-
- for (Object key : set1) {
- // make sure each key is in both key sets
- if (!obj2.containsKey(key))
- return false;
-
- // now compare the corresponding values
- if (!this.isSamePrivate(obj1.get(key), obj2.get(key)))
- return false;
- }
-
- // all tests passed
- return true;
- }
-
- /**
- * Determine whether two Set objects contain the same data
- *
- * @param obj1
- * the first Set dataset
- * @param obj2
- * the second Set dataset
- * @return true if the two sets contain the same elements, compared by
- * using the Java equals method.
- */
- protected boolean isSameSetPrivate(Set obj1, Set obj2) {
- // make sure both sets have the same size number of elements
- if (obj1.size() != obj2.size())
- return false;
-
- // return obj1.containsAll(obj2);
-
- // the sets have the same size - pick one
- for (T item1 : obj1) {
- boolean match = false; // did we find a match for this item?
-
- // make sure each item of the first set matches an item in the
- // second set
- for (T item2 : obj2) {
- // now compare the corresponding values using 'equals' as
- // required
- // for the Set interface
- if (item1.equals(item2))
- match = true; // match found
- }
-
- // no match found for this item
- if (match == false) {
- System.out.println("Mismatch for " + obj1 + " and " + obj2);
- return false;
- }
- }
-
- // all tests passed
- return true;
-
- }
-
- /** ------- THE METHODS USED TO DETERMINE THE TYPES OF OBJECTS ---------- */
- /**
- * Does the class with the given name represent inexact numbers?
- *
- * @param name
- * the name of the class in question
- * @return true if this is double,
- * float, or Double or Float
- */
- protected boolean isDouble(String name) {
- return name.equals("double") || name.equals("java.lang.Double");
- }
-
- /**
- * Does the class with the given name represent inexact numbers?
- *
- * @param name
- * the name of the class in question
- * @return true if this is double, float, or Double or Float
- */
- protected boolean isFloat(String name) {
- return name.equals("float") || name.equals("java.lang.Float");
- }
-
- /**
- * Does the class with the given name represent a wrapper class for a
- * primitive class?
- *
- * @param name
- * the name of the class in question
- * @return true if this is a class that represents a wrapper class
- */
- protected static boolean isWrapperClass(String name) {
- return name.equals("java.lang.Integer")
- || name.equals("java.lang.Long")
- || name.equals("java.lang.Short")
- || name.equals("java.math.BigInteger")
- || name.equals("java.math.BigDecimal")
- || name.equals("java.lang.Float")
- || name.equals("java.lang.Double")
- || name.equals("java.lang.Byte")
- || name.equals("java.lang.Boolean")
- || name.equals("java.lang.Character");
- }
-
- /**
- * Is this a name of one of our Canvas classes?
- *
- * @param name the name of the class to consider
- * @return true if the given name is one of our
- * Canvas classes
- */
- protected static boolean isOurCanvas(String name) {
- return name.equals("draw.Canvas") || name.equals("idraw.Canvas")
- || name.equals("adraw.Canvas") || name.equals("funworld.Canvas")
- || name.equals("impworld.Canvas") || name.equals("appletworld.Canvas")
- || name.equals("javalib.worldcanvas.WorldCanvas")
+// if(showComparisonDetail){
+// System.out.println("Comparing:-");
+// System.out.println("\tclass 1:" + r1.sampleClass.getName()
+// + "; hashcode:" + i1);
+// System.out.println("\tclass 2:" + r2.sampleClass.getName()
+// + "; hashcode:" + i2);
+// System.out.println("\tpair-hashmap key:" + i1 * i1 + i2 * i2);
+// }
+
+ Integer i2match = this.hashmap.get(i1 * i1 + i2 * i2);
+ /*
+ * <>
+ * [Author: Sachin Venugopalan; Date: 03/03/2012]
+ * In order to handle circularity, we need to keep track of pairs of
+ * objects that have already been compared for equality (or for
+ * which an equality check has already been initiated, and is
+ * pending completion owing to a circular definition). In order to
+ * look up pairs of already-seen objects efficiently, we need a
+ * hash-based lookup directory such as a Hashset. The "key" (or
+ * identifier) that is stored in the lookup directory should
+ * identify the pair of objects; also it ought to be "symmetrical"
+ * i.e. the pair of objects is not to be treated as an ordered pair
+ * -- this stems from the fact that equality (rather, "sameness")
+ * between two objects itself is a symmetrical relationship.
+ * In other words, having seen the pair (obj1, obj2) is identical to
+ * having seen the pair (obj2, obj1) We have chosen i1*i1 + i2*i2 to
+ * be this symmetrical identifier of the pair of objects, where i1 &
+ * i2 are their (original) hashcodes. This choice is perhaps better
+ * than i1*i2, say, because such an alternate choice potentially
+ * leads to more collisions. However, there is no absolute guarantee
+ * of uniqueness of i1*i1 + i2*i2 (simply because there is no
+ * absolute guarantee of uniqueness of i1 and i2; we simply assume
+ * their uniqueness for all practical purposes, given Java's current
+ * implementation of hashcodes that relates to the unique memory
+ * locations at which objects reside) Hence, we perform a second
+ * "validation" step to confirm the identity of the pair of objects
+ * by seeing if they map to a chosen value i1+i2 (note that this is
+ * again symmetric) The second validation step may not be very
+ * meaningful, and for the time being, it exists more for legacy reasons.
+ */
+ if ((i2match != null) && (i2match.equals(i1 + i2))) {
+// if(showComparisonDetail)
+// System.out.println("\tcheck done already for this pair:" + i1
+// * i1 + i2 * i2 + " => " + i2match.toString());
+ return true;
+ }
+ this.hashmap.put(i1 * i1 + i2 * i2, i1 + i2);
+
+ /** handle Array objects */
+ if (obj1.getClass().isArray() && obj2.getClass().isArray()
+ && obj1.getClass() == obj2.getClass()) {
+ int length = Array.getLength(obj1);
+ if (Array.getLength(obj2) == length) {
+ for (int i = 0; i < length; i++) {
+ if (!isSame(Array.get(obj1, i), Array.get(obj2, i)))
+ return false;
+ }
+ return true;
+ } else // not same length
+ return false;
+ }
+
+ /** handle ISame objects by delegating to the user-defined method */
+ if ((obj1 instanceof ISame) && (obj2 instanceof ISame))
+ return ((ISame) obj1).same((ISame) obj2);
+
+ /**
+ * handle the Set objects in the Java Collection library by
+ * comparing their size, and data items -- here we use the equals
+ * method when comparing the set elements
+ */
+ if ((obj1 instanceof Set) && (obj2 instanceof Set)
+ && obj1.getClass().getName().startsWith("java.util"))
+ return isSameSet((Set) obj1, (Set) obj2);
+
+ /**
+ * handle Iterable objects in the Java Collection library by
+ * comparing their size, then comparing the elements pairwise
+ */
+ if ((obj1 instanceof Iterable) && (obj2 instanceof Iterable)
+ && obj1.getClass().getName().startsWith("java.util"))
+ return isSameIterablePrivate((Iterable) obj1,
+ (Iterable) obj2);
+
+ /**
+ * handle the Map objects in the Java Collection library by
+ * comparing their size, the key-set, and key-value mappings
+ */
+ if ((obj1 instanceof Map) && (obj2 instanceof Map)
+ && obj1.getClass().getName().startsWith("java.util"))
+ return isSameMap((Map) obj1, (Map) obj2);
+
+ /** now handle the general case */
+ if (sameClass) {
+ boolean sameValues = true;
+ int i = 0;
+ try {
+ for (; i < Array.getLength(r1.sampleDeclaredFields); i++) {
+ sameValues = sameValues
+ && isSamePrivate(
+ r1.sampleDeclaredFields[i].get(obj1),
+ r2.sampleDeclaredFields[i].get(obj2));
+ }
+ } catch (IllegalAccessException e) {
+ System.out.println("same comparing "
+ + r1.sampleDeclaredFields[i].getType().getName()
+ + " and "
+ + r2.sampleDeclaredFields[i].getType().getName()
+ + "cannot access the field " + i + " message: "
+ + e.getMessage());
+ System.out.println("class 1: " + r1.sampleClass.getName());
+ System.out.println("class 2: " + r2.sampleClass.getName());
+ }
+
+ return sameValues;
+ } else // not same class
+ return false;
+ }
+
+ /**
+ * Determine whether the relative difference between two double numbers is
+ * below the expected TOLERANCE Measure absolute tolerance, if
+ * one of the numbers is exact zero.
+ *
+ * @param d1
+ * the first inexact number
+ * @param d2
+ * the second inexact number
+ * @return true is the two numbers are nearly the same
+ */
+ protected boolean isSameDouble(double d1, double d2) {
+ if (d1 - d2 == 0.0)
+ return true;
+ else {
+ INEXACT_COMPARED = true;
+ if (d1 == 0.0)
+ return Math.abs(d2) < TOLERANCE;
+ if (d2 == 0.0)
+ return Math.abs(d1) < TOLERANCE;
+
+ else
+ // d1, d2 are non-zero
+ // return (Math.abs(d1 - d2) / (Math.max (Math.abs(d1),
+ // Math.abs(d2))))
+ return Math.abs(d1 - d2) / (Math.abs((d1 + d2) / 2)) < TOLERANCE;
+ }
+ }
+
+ /**
+ * Determine whether the relative difference between two float numbers is
+ * below the expected TOLERANCE Measure absolute tolerance, if
+ * one of the numbers is exact zero.
+ *
+ * @param f1
+ * the first inexact number
+ * @param f2
+ * the second inexact number
+ * @return true is the two numbers are nearly the same
+ */
+ protected boolean isSameFloat(float f1, float f2) {
+ if (f1 - f2 == 0.0)
+ return true;
+ else {
+ INEXACT_COMPARED = true;
+ Double d1 = ((Float) f1).doubleValue();
+ Double d2 = ((Float) f2).doubleValue();
+
+ if (f1 == 0.0)
+ return Math.abs(d2) < TOLERANCE;
+ if (f2 == 0.0)
+ return Math.abs(d1) < TOLERANCE;
+
+ // f1, f2 are non-zero
+ return (Math.abs(d1 - d2) / (Math.max(Math.abs(d1), Math.abs(d2)))) < TOLERANCE;
+ }
+ }
+
+ /**
+ * Determine whether two Iterable objects generate the same
+ * data elements in the same order.
+ *
+ * @param obj1
+ * the first Iterable dataset
+ * @param obj2
+ * the second Iterable dataset
+ * @return true is the two datasets are extensionally equal
+ */
+ private boolean isSameIterablePrivate(Iterable obj1, Iterable obj2) {
+ Iterator it1 = obj1.iterator();
+ Iterator it2 = obj2.iterator();
+
+ return this.isSameData(it1, it2);
+ }
+
+ /**
+ * Determine whether two Traversal objects generate the same
+ * data elements in the same order.
+ *
+ * @param obj1
+ * the first Traversal dataset
+ * @param obj2
+ * the second Traversal dataset
+ * @return true is the two datasets are extensionally equal
+ */
+ private boolean isSameTraversalPrivate(Traversal obj1,
+ Traversal obj2) {
+ Traversal it1 = obj1;
+ Traversal it2 = obj2;
+
+ return this.isSameTraversalData(it1, it2);
+ }
+
+ /**
+ * Determine whether two Iterators generate the same data in
+ * the same order.
+ *
+ * @param it1
+ * the first Iterator
+ * @param it2
+ * the second Iterator
+ * @return true is both datasets contained the same data elements (in the
+ * same order)
+ */
+ protected boolean isSameData(Iterator it1, Iterator it2) {
+ /** if the first dataset is empty, the second one has to be too */
+ if (!it1.hasNext()) {
+ return !it2.hasNext();
+ }
+ /** the first dataset is nonempty - make sure the second one is too... */
+ else if (!it2.hasNext())
+ return false;
+ /** now both have data - compare the next pair of data and recur */
+ else {
+ return this.isSamePrivate(it1.next(), it2.next())
+ && this.isSameData(it1, it2);
+ }
+ }
+
+ /**
+ * Determine whether two Traversals generate the same data in
+ * the same order.
+ *
+ * @param tr1
+ * the first Traversal
+ * @param tr2
+ * the second Traversal
+ * @return true is both datasets contained the same data elements
+ * (in the same order)
+ */
+ protected boolean isSameTraversalData(Traversal tr1, Traversal tr2) {
+ /** if the first dataset is empty, the second one has to be too */
+ if (tr1.isEmpty()) {
+ return tr2.isEmpty();
+ }
+ /** the first dataset is nonempty - make sure the second one is too... */
+ else if (tr2.isEmpty())
+ return false;
+ /** now both have data - compare the next pair of data and recur */
+ else {
+ return this.isSamePrivate(tr1.getFirst(), tr2.getFirst())
+ && this.isSameTraversalData(tr1.getRest(), tr2.getRest());
+ }
+ }
+
+ /**
+ * Determine whether two Map objects have the same key-value
+ * sets of data
+ *
+ * @param obj1
+ * the first Map dataset
+ * @param obj2
+ * the second Map dataset
+ * @return true if the two maps are extensionally equal
+ */
+ protected boolean isSameMap(Map obj1, Map obj2) {
+ // make sure both maps have the same size keyset
+ if (obj1.size() != obj2.size())
+ return false;
+
+ // the key sets for the two maps have the same size - pick one
+ Set set1 = obj1.keySet();
+
+ for (Object key : set1) {
+ // make sure each key is in both key sets
+ if (!obj2.containsKey(key))
+ return false;
+
+ // now compare the corresponding values
+ if (!this.isSamePrivate(obj1.get(key), obj2.get(key)))
+ return false;
+ }
+
+ // all tests passed
+ return true;
+ }
+
+ /**
+ * Determine whether two Set objects contain the same data
+ *
+ * @param obj1
+ * the first Set dataset
+ * @param obj2
+ * the second Set dataset
+ * @return true if the two sets contain the same elements, compared by
+ * using the Java equals method.
+ */
+ protected boolean isSameSetPrivate(Set obj1, Set obj2) {
+ // make sure both sets have the same size number of elements
+ if (obj1.size() != obj2.size())
+ return false;
+
+ // return obj1.containsAll(obj2);
+
+ // the sets have the same size - pick one
+ for (T item1 : obj1) {
+ boolean match = false; // did we find a match for this item?
+
+ // make sure each item of the first set matches an item in the
+ // second set
+ for (T item2 : obj2) {
+ // now compare the corresponding values using 'equals' as
+ // required
+ // for the Set interface
+ if (item1.equals(item2))
+ match = true; // match found
+ }
+
+ // no match found for this item
+ if (match == false) {
+ System.out.println("Mismatch for " + obj1 + " and " + obj2);
+ return false;
+ }
+ }
+
+ // all tests passed
+ return true;
+
+ }
+
+ /** ------- THE METHODS USED TO DETERMINE THE TYPES OF OBJECTS ---------- */
+ /**
+ * Does the class with the given name represent inexact numbers?
+ *
+ * @param name
+ * the name of the class in question
+ * @return true if this is double,
+ * float, or Double or Float
+ */
+ protected boolean isDouble(String name) {
+ return name.equals("double") || name.equals("java.lang.Double");
+ }
+
+ /**
+ * Does the class with the given name represent inexact numbers?
+ *
+ * @param name
+ * the name of the class in question
+ * @return true if this is double, float, or Double or Float
+ */
+ protected boolean isFloat(String name) {
+ return name.equals("float") || name.equals("java.lang.Float");
+ }
+
+ /**
+ * Does the class with the given name represent a wrapper class for a
+ * primitive class?
+ *
+ * @param name
+ * the name of the class in question
+ * @return true if this is a class that represents a wrapper class
+ */
+ protected static boolean isWrapperClass(String name) {
+ return name.equals("java.lang.Integer")
+ || name.equals("java.lang.Long")
+ || name.equals("java.lang.Short")
+ || name.equals("java.math.BigInteger")
+ || name.equals("java.math.BigDecimal")
+ || name.equals("java.lang.Float")
+ || name.equals("java.lang.Double")
+ || name.equals("java.lang.Byte")
+ || name.equals("java.lang.Boolean")
+ || name.equals("java.lang.Character");
+ }
+
+ /**
+ * Is this a name of one of our Canvas classes?
+ *
+ * @param name the name of the class to consider
+ * @return true if the given name is one of our
+ * Canvas classes
+ */
+ protected static boolean isOurCanvas(String name) {
+ return name.equals("draw.Canvas") || name.equals("idraw.Canvas")
+ || name.equals("adraw.Canvas") || name.equals("funworld.Canvas")
+ || name.equals("impworld.Canvas") || name.equals("appletworld.Canvas")
+ || name.equals("javalib.worldcanvas.WorldCanvas")
|| name.equals("javalib.worldcanvas.AppletCanvas")
- || name.equals("impsoundworld.Canvas")
+ || name.equals("impsoundworld.Canvas")
|| name.equals("appletsoundworld.Canvas");
- }
+ }
/**
* Is this a name of one of classes in the javalib.tunes
@@ -750,66 +754,67 @@ protected static boolean isTunesPackage(String name) {
return name.startsWith("javalib.tunes.");
}
- /**
- * If obj1 is an instance of one of the IColors
- * compare the objects by just checking that the class names are the same
- *
- * @param obj1
- * the object that could be an IColor
- * @param obj2
- * the object we are comparing with
- * @return true if the test succeeds
- */
- protected boolean checkIColors(T obj1, T obj2) {
- /** Convert IColor-s from the colors teachpack to java.awt.Color */
- if (obj1.getClass().getName().equals("colors.Red"))
- return obj2.getClass().getName().equals("colors.Red");
- if (obj1.getClass().getName().equals("colors.White"))
- return obj2.getClass().getName().equals("colors.White");
- if (obj1.getClass().getName().equals("colors.Blue"))
- return obj2.getClass().getName().equals("colors.Blue");
- if (obj1.getClass().getName().equals("colors.Black"))
- return obj2.getClass().getName().equals("colors.Black");
- if (obj1.getClass().getName().equals("colors.Green"))
- return obj2.getClass().getName().equals("colors.Green");
- if (obj1.getClass().getName().equals("colors.Yellow"))
- return obj2.getClass().getName().equals("colors.Yellow");
- return false;
- }
-
- /**
- * If name is the name of one of the classes that
- * extend the WorldImage class within the interim
- * implementation of the World library,
- * compare the objects by just checking that the class names are the same
- *
- * Note: The new (javalib package) implementation supports
- * the comparison of images that checks the relevant image parameters
- * (size, color, pinhole location, etc.) It also moved the definition of the
- * WorldImage class hierarchy into its own package, eliminating the
- * code duplication.
- *
- * @param name
- * the class name that could be the name of the old WorldImage class
- * @return true if the the given name matches one of the class names in the old
- * WorldImage hierarchy
- */
- protected static boolean isWorldImage(String name){
- ArrayList worldPackageNames = new ArrayList(Arrays.asList(
- "funworld", "impworld", "appletworld",
- "impsoundworld", "appletsoundworld"));
- ArrayList worldImageClassNames = new ArrayList(Arrays.asList(
- "CircleImage", "DiskImage", "EllipseImage", "FrameImage",
- "FromFileImage", "LineImage", "OvalImage", "OverlayImages",
- "OverlayImagesXY", "RectangleImage", "TextImage"));
- for(String packagename: worldPackageNames){
- if (name.startsWith(packagename))
-
- for (String classname : worldImageClassNames){
- if (name.endsWith(classname))
- return true;
- }
- }
- return false;
- }
-}
\ No newline at end of file
+ /**
+ * If obj1 is an instance of one of the IColors
+ * compare the objects by just checking that the class names are the same
+ *
+ * @param obj1
+ * the object that could be an IColor
+ * @param obj2
+ * the object we are comparing with
+ * @return true if the test succeeds
+ */
+ protected boolean checkIColors(T obj1, T obj2) {
+ /** Convert IColor-s from the colors teachpack to java.awt.Color */
+ if (obj1.getClass().getName().equals("colors.Red"))
+ return obj2.getClass().getName().equals("colors.Red");
+ if (obj1.getClass().getName().equals("colors.White"))
+ return obj2.getClass().getName().equals("colors.White");
+ if (obj1.getClass().getName().equals("colors.Blue"))
+ return obj2.getClass().getName().equals("colors.Blue");
+ if (obj1.getClass().getName().equals("colors.Black"))
+ return obj2.getClass().getName().equals("colors.Black");
+ if (obj1.getClass().getName().equals("colors.Green"))
+ return obj2.getClass().getName().equals("colors.Green");
+ if (obj1.getClass().getName().equals("colors.Yellow"))
+ return obj2.getClass().getName().equals("colors.Yellow");
+ return false;
+ }
+
+ /**
+ * If name is the name of one of the classes that
+ * extend the WorldImage class within the interim
+ * implementation of the World library,
+ * compare the objects by just checking that the class names are the same
+ *
+ * Note: The new (javalib package) implementation supports
+ * the comparison of images that checks the relevant image parameters
+ * (size, color, pinhole location, etc.) It also moved the definition of the
+ * WorldImage class hierarchy into its own package, eliminating the
+ * code duplication.
+ *
+ * @param name
+ * the class name that could be the name of the old WorldImage class
+ * @return true if the the given name matches one of the class names in the old
+ * WorldImage hierarchy
+ */
+ protected static boolean isWorldImage(String name){
+ ArrayList worldPackageNames = new ArrayList(Arrays.asList(
+ "funworld", "impworld", "appletworld",
+ "impsoundworld", "appletsoundworld"));
+ ArrayList worldImageClassNames = new ArrayList(Arrays.asList(
+ "CircleImage", "Crop", "EllipseImage",
+ "FreezeImage", "FromFileImage", "FromURLImage", "LinearImage",
+ "OverlayImage", "PolygonImage", "RasterImage",
+ "RectangleImage", "TextImage"));
+ for(String packagename: worldPackageNames){
+ if (name.startsWith(packagename))
+
+ for (String classname : worldImageClassNames){
+ if (name.endsWith(classname))
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/tester/Tester.java b/src/tester/Tester.java
index 694105a..be76a0e 100644
--- a/src/tester/Tester.java
+++ b/src/tester/Tester.java
@@ -1850,6 +1850,23 @@ public boolean checkEquivalent(T obj1, T obj2,
return this.checkEquivalent(obj1, obj2, equiv, "");
}
+ /**
+ * Use the given {@link Equivalence Equivalence}
+ * function object to determine the NON-equivalence
+ * of the two given objects.
+ *
+ * @param obj1 the first object to compare
+ * @param obj2 the second object to compare
+ * @param equiv the function object that implements the
+ * {@link Equivalence Equivalence} comparison
+ *
+ * @return true if the two objects are equivalent
+ */
+ public boolean checkInequivalent(T obj1, T obj2,
+ Equivalence equiv) {
+ return this.checkInequivalent(obj1, obj2, equiv, "");
+ }
+
/**
* Use the given {@link Equivalence Equivalence}
* function object to determine the equivalence
@@ -1870,6 +1887,25 @@ public boolean checkEquivalent(T obj1, T obj2,
this.combine(obj1, obj2));
}
+ /**
+ * Use the given {@link Equivalence Equivalence}
+ * function object to determine the equivalence
+ * of the two given objects.
+ *
+ * @param obj1 the first object to compare
+ * @param obj2 the second object to compare
+ * @param equiv the function object that implements the
+ * {@link Equivalence Equivalence} comparison
+ * @param testname the String that describes this test
+ *
+ * @return true if the two objects are equivalent
+ */
+ public boolean checkInequivalent(T obj1, T obj2,
+ Equivalence equiv, String testname) {
+ this.testname = "Equivalence test: \n" + testname;
+ return this.checkExpect(! equiv.equivalent(obj1, obj2), "Should be inequivalent: \n" + testname);
+ }
+
/*--------------------------------------------------------------------*/
/*---------- HELPERS FOR THE TEST EVALUATION SECTION -----------------*/
/*--------------------------------------------------------------------*/
@@ -2518,9 +2554,10 @@ protected void fullTestReport() {
* @param obj
* The 'Examples' class instance where the tests are defined
*/
- public static void run(Object obj) {
+ public static boolean run(Object obj) {
Tester t = new Tester();
t.runAnyTests(obj, false, true);
+ return t.errors==0;
}
/**
@@ -2529,13 +2566,14 @@ public static void run(Object obj) {
*
* @param objs An array of 'Examples' class instances where tests are defined
*/
- public static void runFullReport(Object... objs) {
+ public static boolean runFullReport(Object... objs) {
Tester t = new Tester();
if(objs != null){
for(Object obj : objs){
t.runAnyTests(obj, true, true);
}
}
+ return t.errors==0;
}
/**
@@ -2544,9 +2582,10 @@ public static void runFullReport(Object... objs) {
*
* @param obj The 'Examples' class instance where the tests are defined
*/
- public static void runReport(Object obj, boolean full, boolean printall) {
+ public static boolean runReport(Object obj, boolean full, boolean printall) {
Tester t = new Tester();
t.runAnyTests(obj, full, printall);
+ return t.errors==0;
}
/**
@@ -2557,7 +2596,7 @@ public static void runReport(Object obj, boolean full, boolean printall) {
* @param printall true if all data should be displayed
* @param objs An array of 'Examples' class instances where tests are defined
*/
- public static void runReports(boolean full, boolean printall,
+ public static boolean runReports(boolean full, boolean printall,
Object... objs) {
Tester t = new Tester();
if(objs != null){
@@ -2565,5 +2604,6 @@ public static void runReports(boolean full, boolean printall,
t.runAnyTests(obj, full, printall);
}
}
+ return t.errors==0;
}
-}
\ No newline at end of file
+}