| // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | // This tests uses the multi-test "ok" feature: | 
 | // none: Trimmed behaviour. Passing on the VM. | 
 | // 01: Trimmed version for dart2js. | 
 | // 02: Full version passing in the VM. | 
 | // | 
 | // TODO(rmacnak,ahe): Remove multi-test when VM and dart2js are on par. | 
 |  | 
 | library test.class_equality_test; | 
 |  | 
 | import 'dart:mirrors'; | 
 |  | 
 | import 'package:expect/expect.dart'; | 
 |  | 
 | class A<T> {} | 
 |  | 
 | class B extends A<int> {} | 
 |  | 
 | class BadEqualityHash { | 
 |   int count = 0; | 
 |   bool operator ==(other) => true; | 
 |   int get hashCode => count++; | 
 | } | 
 |  | 
 | typedef bool Predicate(Object o); | 
 | Predicate somePredicate = (Object o) => false; | 
 |  | 
 | checkEquality(List<Map<String, Object?>> equivalenceClasses) { | 
 |   for (var equivalenceClass in equivalenceClasses) { | 
 |     equivalenceClass.forEach((name, member) { | 
 |       equivalenceClass.forEach((otherName, otherMember) { | 
 |         // Reflexivity, symmetry and transitivity. | 
 |         Expect.equals(member, otherMember, "$name == $otherName"); | 
 |         Expect.equals(member.hashCode, otherMember.hashCode, | 
 |             "$name.hashCode == $otherName.hashCode"); | 
 |       }); | 
 |       for (var otherEquivalenceClass in equivalenceClasses) { | 
 |         if (otherEquivalenceClass == equivalenceClass) continue; | 
 |         otherEquivalenceClass.forEach((otherName, otherMember) { | 
 |           Expect.notEquals( | 
 |               member, otherMember, "$name != $otherName"); // Exclusion. | 
 |           // Hash codes may or may not be equal. | 
 |         }); | 
 |       } | 
 |     }); | 
 |   } | 
 | } | 
 |  | 
 | void subroutine() {} | 
 |  | 
 | main() { | 
 |   LibraryMirror thisLibrary = currentMirrorSystem() | 
 |       .findLibrary(const Symbol('test.class_equality_test')); | 
 |  | 
 |   var o1 = new Object(); | 
 |   var o2 = new Object(); | 
 |  | 
 |   var badEqualityHash1 = new BadEqualityHash(); | 
 |   var badEqualityHash2 = new BadEqualityHash(); | 
 |  | 
 |   checkEquality(<Map<String, Object?>>[ | 
 |     {'reflect(o1)': reflect(o1), 'reflect(o1), again': reflect(o1)}, | 
 |     {'reflect(o2)': reflect(o2), 'reflect(o2), again': reflect(o2)}, | 
 |     { | 
 |       'reflect(badEqualityHash1)': reflect(badEqualityHash1), | 
 |       'reflect(badEqualityHash1), again': reflect(badEqualityHash1) | 
 |     }, | 
 |     { | 
 |       'reflect(badEqualityHash2)': reflect(badEqualityHash2), | 
 |       'reflect(badEqualityHash2), again': reflect(badEqualityHash2) | 
 |     }, | 
 |     {'reflect(true)': reflect(true), 'reflect(true), again': reflect(true)}, | 
 |     {'reflect(false)': reflect(false), 'reflect(false), again': reflect(false)}, | 
 |     {'reflect(null)': reflect(null), 'reflect(null), again': reflect(null)}, | 
 |     { | 
 |       'reflect(3.5+4.5)': reflect(3.5 + 4.5), | 
 |       'reflect(6.5+1.5)': reflect(6.5 + 1.5) | 
 |     }, | 
 |     {'reflect(3+4)': reflect(3 + 4), 'reflect(6+1)': reflect(6 + 1)}, | 
 |     {'reflect("foo")': reflect("foo"), 'reflect("foo"), again': reflect("foo")}, | 
 |     { | 
 |       'currentMirrorSystem().voidType': currentMirrorSystem().voidType, | 
 |       'thisLibrary.declarations[#subroutine].returnType': | 
 |           (thisLibrary.declarations[#subroutine] as MethodMirror).returnType | 
 |     }, | 
 |     { | 
 |       'currentMirrorSystem().dynamicType': currentMirrorSystem().dynamicType, | 
 |       'thisLibrary.declarations[#main].returnType': | 
 |           (thisLibrary.declarations[#main] as MethodMirror).returnType | 
 |     }, | 
 |     { | 
 |       'reflectClass(A)': reflectClass(A), | 
 |       'thisLibrary.declarations[#A]': thisLibrary.declarations[#A], | 
 |       'reflect(new A<int>()).type.originalDeclaration': | 
 |           reflect(new A<int>()).type.originalDeclaration | 
 |     }, | 
 |     { | 
 |       'reflectClass(B).superclass': reflectClass(B).superclass, | 
 |       'reflect(new A<int>()).type': reflect(new A<int>()).type | 
 |     }, | 
 |     { | 
 |       'reflectClass(B)': reflectClass(B), | 
 |       'thisLibrary.declarations[#B]': thisLibrary.declarations[#B], | 
 |       'reflect(new B()).type': reflect(new B()).type | 
 |     }, | 
 |     { | 
 |       'reflectClass(BadEqualityHash).declarations[#==]': | 
 |           reflectClass(BadEqualityHash).declarations[#==], | 
 |       'reflect(new BadEqualityHash()).type.declarations[#==]': | 
 |           reflect(new BadEqualityHash()).type.declarations[#==] | 
 |     }, | 
 |     { | 
 |       'reflectClass(BadEqualityHash).declarations[#==].parameters[0]': | 
 |           (reflectClass(BadEqualityHash).declarations[#==] as MethodMirror) | 
 |               .parameters[0], | 
 |       'reflect(new BadEqualityHash()).type.declarations[#==].parameters[0]': | 
 |           (reflect(new BadEqualityHash()).type.declarations[#==] | 
 |                   as MethodMirror) | 
 |               .parameters[0] | 
 |     }, | 
 |     { | 
 |       'reflectClass(BadEqualityHash).declarations[#count]': | 
 |           reflectClass(BadEqualityHash).declarations[#count], | 
 |       'reflect(new BadEqualityHash()).type.declarations[#count]': | 
 |           reflect(new BadEqualityHash()).type.declarations[#count] | 
 |     }, | 
 |     { | 
 |       'reflectType(Predicate)': reflectType(Predicate), | 
 |       'thisLibrary.declarations[#somePredicate].type': | 
 |           (thisLibrary.declarations[#somePredicate] as VariableMirror).type | 
 |     }, | 
 |     { | 
 |       'reflectType(Predicate).referent': | 
 |           (reflectType(Predicate) as TypedefMirror).referent, | 
 |       'thisLibrary.declarations[#somePredicate].type.referent': | 
 |           ((thisLibrary.declarations[#somePredicate] as VariableMirror).type | 
 |                   as TypedefMirror) | 
 |               .referent | 
 |     }, | 
 |     { | 
 |       'reflectClass(A).typeVariables.single': | 
 |           reflectClass(A).typeVariables.single, | 
 |       'reflect(new A<int>()).type.originalDeclaration.typeVariables.single': | 
 |           reflect(new A<int>()).type.originalDeclaration.typeVariables.single | 
 |     }, | 
 |     {'currentMirrorSystem()': currentMirrorSystem()}, | 
 |     {'currentMirrorSystem().isolate': currentMirrorSystem().isolate}, | 
 |     { | 
 |       'thisLibrary': thisLibrary, | 
 |       'reflectClass(A).owner': reflectClass(A).owner, | 
 |       'reflectClass(B).owner': reflectClass(B).owner, | 
 |       'reflect(new A()).type.owner': reflect(new A()).type.owner, | 
 |       'reflect(new B()).type.owner': reflect(new B()).type.owner | 
 |     }, | 
 |   ]); | 
 | } |