OLD | NEW |
| (Empty) |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 import 'package:kernel/kernel.dart'; | |
6 import 'package:kernel/class_hierarchy.dart'; | |
7 import 'package:test/test.dart'; | |
8 import 'class_hierarchy_basic.dart'; | |
9 import 'dart:io'; | |
10 import 'dart:math'; | |
11 | |
12 void testClassHierarchyOnProgram(Program program, {bool verbose: false}) { | |
13 BasicClassHierarchy basic = new BasicClassHierarchy(program); | |
14 ClassHierarchy classHierarchy = new ClassHierarchy(program); | |
15 int total = classHierarchy.classes.length; | |
16 int progress = 0; | |
17 for (var class1 in classHierarchy.classes) { | |
18 for (var class2 in classHierarchy.classes) { | |
19 bool isSubclass = classHierarchy.isSubclassOf(class1, class2); | |
20 bool isSubmixture = classHierarchy.isSubmixtureOf(class1, class2); | |
21 bool isSubtype = classHierarchy.isSubtypeOf(class1, class2); | |
22 var asInstance = classHierarchy.getClassAsInstanceOf(class1, class2); | |
23 if (isSubclass != basic.isSubclassOf(class1, class2)) { | |
24 fail('isSubclassOf(${class1.name}, ${class2.name}) returned ' | |
25 '$isSubclass but should be ${!isSubclass}'); | |
26 } | |
27 if (isSubmixture != basic.isSubmixtureOf(class1, class2)) { | |
28 fail('isSubmixtureOf(${class1.name}, ${class2.name}) returned ' | |
29 '$isSubclass but should be ${!isSubclass}'); | |
30 } | |
31 if (isSubtype != basic.isSubtypeOf(class1, class2)) { | |
32 fail('isSubtypeOf(${class1.name}, ${class2.name}) returned ' | |
33 '$isSubtype but should be ${!isSubtype}'); | |
34 } | |
35 if (asInstance != basic.getClassAsInstanceOf(class1, class2)) { | |
36 fail('asInstanceOf(${class1.name}, ${class2.name}) returned ' | |
37 '$asInstance but should be ' | |
38 '${basic.getClassAsInstanceOf(class1, class2)}'); | |
39 } | |
40 } | |
41 ++progress; | |
42 if (verbose) { | |
43 stdout.write('\rSubclass queries ${100 * progress ~/ total}%'); | |
44 } | |
45 } | |
46 Set<Name> names = new Set<Name>(); | |
47 for (var classNode in classHierarchy.classes) { | |
48 for (var member in classNode.members) { | |
49 names.add(member.name); | |
50 } | |
51 } | |
52 List<Name> nameList = names.toList(); | |
53 progress = 0; | |
54 for (var classNode in classHierarchy.classes) { | |
55 Iterable<Name> candidateNames = <Iterable<Name>>[ | |
56 basic.gettersAndCalls[classNode].keys, | |
57 basic.setters[classNode].keys, | |
58 pickRandom(nameList, 100) | |
59 ].expand((x) => x); | |
60 for (Name name in candidateNames) { | |
61 Member expectedGetter = | |
62 basic.getDispatchTarget(classNode, name, setter: false); | |
63 Member expectedSetter = | |
64 basic.getDispatchTarget(classNode, name, setter: true); | |
65 Member actualGetter = | |
66 classHierarchy.getDispatchTarget(classNode, name, setter: false); | |
67 Member actualSetter = | |
68 classHierarchy.getDispatchTarget(classNode, name, setter: true); | |
69 if (actualGetter != expectedGetter) { | |
70 fail('lookupGetter($classNode, $name) returned ' | |
71 '$actualGetter but should be $expectedGetter'); | |
72 } | |
73 if (actualSetter != expectedSetter) { | |
74 fail('lookupSetter($classNode, $name) returned ' | |
75 '$actualSetter but should be $expectedSetter'); | |
76 } | |
77 } | |
78 ++progress; | |
79 if (verbose) { | |
80 stdout.write('\rDispatch queries ${100 * progress ~/ total}%'); | |
81 } | |
82 } | |
83 progress = 0; | |
84 for (var classNode in classHierarchy.classes) { | |
85 Iterable<Name> candidateNames = [ | |
86 basic.interfaceGettersAndCalls[classNode].keys, | |
87 basic.interfaceSetters[classNode].keys, | |
88 pickRandom(nameList, 100) | |
89 ].expand((x) => x); | |
90 for (Name name in candidateNames) { | |
91 Member expectedGetter = | |
92 basic.getInterfaceMember(classNode, name, setter: false); | |
93 Member expectedSetter = | |
94 basic.getInterfaceMember(classNode, name, setter: true); | |
95 Member actualGetter = | |
96 classHierarchy.getInterfaceMember(classNode, name, setter: false); | |
97 Member actualSetter = | |
98 classHierarchy.getInterfaceMember(classNode, name, setter: true); | |
99 if (actualGetter != expectedGetter) { | |
100 fail('getInterfaceMember($classNode, $name) returned ' | |
101 '$actualGetter but should be $expectedGetter'); | |
102 } | |
103 if (actualSetter != expectedSetter) { | |
104 fail('getInterfaceMember($classNode, $name, setter: true) ' | |
105 'returned $actualSetter but should be $expectedSetter'); | |
106 } | |
107 } | |
108 ++progress; | |
109 if (verbose) { | |
110 stdout.write('\rInterface queries ${100 * progress ~/ total}%'); | |
111 } | |
112 } | |
113 for (var classNode in classHierarchy.classes) { | |
114 String getHash(member, superMember, setter) { | |
115 String eq = setter ? '=' : ''; | |
116 return '$member$eq overrides $superMember$eq'; | |
117 } | |
118 Set<String> expectedOverrides = new Set<String>(); | |
119 basic.forEachOverridePair(classNode, (member, superMember, setter) { | |
120 expectedOverrides.add(getHash(member, superMember, setter)); | |
121 }); | |
122 Set<String> actualOverrides = new Set<String>(); | |
123 classHierarchy.forEachOverridePair(classNode, (member, superMember, setter)
{ | |
124 actualOverrides.add(getHash(member, superMember, setter)); | |
125 }); | |
126 for (var actual in actualOverrides) { | |
127 if (!expectedOverrides.contains(actual)) { | |
128 fail("forEachOverridePair($classNode) should not report that $actual"); | |
129 } | |
130 } | |
131 for (var expected in expectedOverrides) { | |
132 if (!actualOverrides.contains(expected)) { | |
133 fail("forEachOverridePair($classNode) did not report that $expected"); | |
134 } | |
135 } | |
136 } | |
137 if (verbose) { | |
138 print('\rProgress 100%. Done.'); | |
139 } | |
140 } | |
141 | |
142 var random = new Random(12345); | |
143 | |
144 List/*<T>*/ pickRandom/*<T>*/(List/*<T>*/ items, int n) { | |
145 var result = /*<T>*/[]; | |
146 for (int i = 0; i < n; ++i) { | |
147 result.add(items[random.nextInt(items.length)]); | |
148 } | |
149 return result; | |
150 } | |
OLD | NEW |