OLD | NEW |
| (Empty) |
1 // Copyright (c) 2014, 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 library test.integration.search.domain; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import 'package:analysis_testing/reflective_tests.dart'; | |
10 import 'package:unittest/unittest.dart'; | |
11 | |
12 import 'integration_tests.dart'; | |
13 | |
14 /** | |
15 * Results of a getTypeHierarchy request, processed for easier testing. | |
16 */ | |
17 class HierarchyResults { | |
18 /** | |
19 * The list of hierarchy items from the result. | |
20 */ | |
21 List<Map> items; | |
22 | |
23 /** | |
24 * The first hierarchy item from the result, which represents the pivot | |
25 * class. | |
26 */ | |
27 Map pivot; | |
28 | |
29 /** | |
30 * A map from element name to item index. | |
31 */ | |
32 Map<String, int> nameToIndex; | |
33 | |
34 /** | |
35 * Create a [HierarchyResults] object based on the result from a | |
36 * getTypeHierarchy request. | |
37 */ | |
38 HierarchyResults(result) { | |
39 items = result['hierarchyItems']; | |
40 pivot = items[0]; | |
41 nameToIndex = <String, int> {}; | |
42 for (int i = 0; i < items.length; i++) { | |
43 nameToIndex[items[i]['classElement']['name']] = i; | |
44 } | |
45 } | |
46 | |
47 /** | |
48 * Get an item by class name. | |
49 */ | |
50 Map getItem(String name) { | |
51 if (nameToIndex.containsKey(name)) { | |
52 return items[nameToIndex[name]]; | |
53 } else { | |
54 fail('Class $name not found in hierarchy results'); | |
55 return null; | |
56 } | |
57 } | |
58 } | |
59 | |
60 @ReflectiveTestCase() | |
61 class SearchDomainIntegrationTest extends AbstractAnalysisServerIntegrationTest | |
62 { | |
63 /** | |
64 * Pathname of the main file to run tests in. | |
65 */ | |
66 String pathname; | |
67 | |
68 test_getTypeHierarchy() { | |
69 pathname = sourcePath('test.dart'); | |
70 // Write a dummy file which will be overridden by tests using | |
71 // [sendAnalysisUpdateContent]. | |
72 writeFile(pathname, '// dummy'); | |
73 standardAnalysisSetup(); | |
74 | |
75 // Run all the getTypeHierarchy tests at once so that the server can take | |
76 // advantage of incremental analysis and the test doesn't time out. | |
77 List tests = [getTypeHierarchy_classElement, getTypeHierarchy_displayName, | |
78 getTypeHierarchy_memberElement, getTypeHierarchy_superclass, | |
79 getTypeHierarchy_interfaces, getTypeHierarchy_mixins, | |
80 getTypeHierarchy_subclasses, getTypeHierarchy_badTarget, | |
81 getTypeHierarchy_functionTarget]; | |
82 return Future.forEach(tests, (test) => test()); | |
83 } | |
84 | |
85 Future getTypeHierarchy_classElement() { | |
86 String text = | |
87 r''' | |
88 class Base {} | |
89 class Pivot /* target */ extends Base {} | |
90 class Derived extends Pivot {} | |
91 '''; | |
92 return typeHierarchyTest(text).then((HierarchyResults results) { | |
93 expect(results.items, hasLength(4)); | |
94 expect(results.nameToIndex['Pivot'], equals(0)); | |
95 void checkElement(String name) { | |
96 // We don't check the full element data structure; just enough to make | |
97 // sure that we're pointing to the correct element. | |
98 Map element = results.items[results.nameToIndex[name]]['classElement']; | |
99 expect(element['kind'], equals('CLASS')); | |
100 expect(element['name'], equals(name)); | |
101 if (name != 'Object') { | |
102 expect(element['location']['offset'], equals(text.indexOf( | |
103 'class $name') + 'class '.length)); | |
104 } | |
105 } | |
106 checkElement('Object'); | |
107 checkElement('Base'); | |
108 checkElement('Pivot'); | |
109 checkElement('Derived'); | |
110 }); | |
111 } | |
112 | |
113 Future getTypeHierarchy_displayName() { | |
114 String text = | |
115 r''' | |
116 class Base<T> {} | |
117 class Pivot /* target */ extends Base<int> {} | |
118 '''; | |
119 return typeHierarchyTest(text).then((HierarchyResults results) { | |
120 expect(results.items, hasLength(3)); | |
121 expect(results.getItem('Object')['displayName'], isNull); | |
122 expect(results.getItem('Base')['displayName'], equals('Base<int>')); | |
123 expect(results.getItem('Pivot')['displayName'], isNull); | |
124 }); | |
125 } | |
126 | |
127 Future getTypeHierarchy_memberElement() { | |
128 String text = | |
129 r''' | |
130 class Base1 { | |
131 void foo /* base1 */ (); | |
132 } | |
133 class Base2 extends Base1 {} | |
134 class Pivot extends Base2 { | |
135 void foo /* target */ (); | |
136 } | |
137 class Derived1 extends Pivot {} | |
138 class Derived2 extends Derived1 { | |
139 void foo /* derived2 */ (); | |
140 }'''; | |
141 return typeHierarchyTest(text).then((HierarchyResults results) { | |
142 expect(results.items, hasLength(6)); | |
143 expect(results.getItem('Object')['memberElement'], isNull); | |
144 expect(results.getItem('Base1')['memberElement']['location']['offset'], | |
145 equals(text.indexOf('foo /* base1 */'))); | |
146 expect(results.getItem('Base2')['memberElement'], isNull); | |
147 expect(results.getItem('Pivot')['memberElement']['location']['offset'], | |
148 equals(text.indexOf('foo /* target */'))); | |
149 expect(results.getItem('Derived1')['memberElement'], isNull); | |
150 expect(results.getItem('Derived2')['memberElement']['location']['offset'], | |
151 equals(text.indexOf('foo /* derived2 */'))); | |
152 }); | |
153 } | |
154 | |
155 Future getTypeHierarchy_superclass() { | |
156 String text = | |
157 r''' | |
158 class Base1 {} | |
159 class Base2 extends Base1 {} | |
160 class Pivot /* target */ extends Base2 {} | |
161 '''; | |
162 return typeHierarchyTest(text).then((HierarchyResults results) { | |
163 expect(results.items, hasLength(4)); | |
164 expect(results.getItem('Object')['superclass'], isNull); | |
165 expect(results.getItem('Base1')['superclass'], equals( | |
166 results.nameToIndex['Object'])); | |
167 expect(results.getItem('Base2')['superclass'], equals( | |
168 results.nameToIndex['Base1'])); | |
169 expect(results.getItem('Pivot')['superclass'], equals( | |
170 results.nameToIndex['Base2'])); | |
171 }); | |
172 } | |
173 | |
174 Future getTypeHierarchy_interfaces() { | |
175 String text = | |
176 r''' | |
177 class Interface1 {} | |
178 class Interface2 {} | |
179 class Pivot /* target */ implements Interface1, Interface2 {} | |
180 '''; | |
181 return typeHierarchyTest(text).then((HierarchyResults results) { | |
182 expect(results.items, hasLength(4)); | |
183 expect(results.pivot['interfaces'], hasLength(2)); | |
184 expect(results.pivot['interfaces'], contains( | |
185 results.nameToIndex['Interface1'])); | |
186 expect(results.pivot['interfaces'], contains( | |
187 results.nameToIndex['Interface2'])); | |
188 expect(results.getItem('Object')['interfaces'], isEmpty); | |
189 expect(results.getItem('Interface1')['interfaces'], isEmpty); | |
190 expect(results.getItem('Interface2')['interfaces'], isEmpty); | |
191 }); | |
192 } | |
193 | |
194 Future getTypeHierarchy_mixins() { | |
195 String text = | |
196 r''' | |
197 class Base {} | |
198 class Mixin1 {} | |
199 class Mixin2 {} | |
200 class Pivot /* target */ extends Base with Mixin1, Mixin2 {} | |
201 '''; | |
202 return typeHierarchyTest(text).then((HierarchyResults results) { | |
203 expect(results.items, hasLength(5)); | |
204 expect(results.pivot['mixins'], hasLength(2)); | |
205 expect(results.pivot['mixins'], contains(results.nameToIndex['Mixin1'])); | |
206 expect(results.pivot['mixins'], contains(results.nameToIndex['Mixin2'])); | |
207 expect(results.getItem('Object')['mixins'], isEmpty); | |
208 expect(results.getItem('Base')['mixins'], isEmpty); | |
209 expect(results.getItem('Mixin1')['mixins'], isEmpty); | |
210 expect(results.getItem('Mixin2')['mixins'], isEmpty); | |
211 }); | |
212 } | |
213 | |
214 Future getTypeHierarchy_subclasses() { | |
215 String text = | |
216 r''' | |
217 class Base {} | |
218 class Pivot /* target */ extends Base {} | |
219 class Sub1 extends Pivot {} | |
220 class Sub2 extends Pivot {} | |
221 class Sub2a extends Sub2 {} | |
222 '''; | |
223 return typeHierarchyTest(text).then((HierarchyResults results) { | |
224 expect(results.items, hasLength(6)); | |
225 expect(results.pivot['subclasses'], hasLength(2)); | |
226 expect(results.pivot['subclasses'], contains(results.nameToIndex['Sub1']) | |
227 ); | |
228 expect(results.pivot['subclasses'], contains(results.nameToIndex['Sub2']) | |
229 ); | |
230 expect(results.getItem('Object')['subclasses'], isEmpty); | |
231 expect(results.getItem('Base')['subclasses'], isEmpty); | |
232 expect(results.getItem('Sub1')['subclasses'], isEmpty); | |
233 expect(results.getItem('Sub2')['subclasses'], equals( | |
234 [results.nameToIndex['Sub2a']])); | |
235 expect(results.getItem('Sub2a')['subclasses'], isEmpty); | |
236 }); | |
237 } | |
238 | |
239 Future getTypeHierarchy_badTarget() { | |
240 String text = | |
241 r''' | |
242 main() { | |
243 if /* target */ (true) { | |
244 print('Hello'); | |
245 } | |
246 } | |
247 '''; | |
248 return typeHierarchyTest(text).then((HierarchyResults results) { | |
249 expect(results, isNull); | |
250 }); | |
251 } | |
252 | |
253 Future getTypeHierarchy_functionTarget() { | |
254 String text = r''' | |
255 main /* target */ () { | |
256 } | |
257 '''; | |
258 return typeHierarchyTest(text).then((HierarchyResults results) { | |
259 expect(results, isNull); | |
260 }); | |
261 } | |
262 | |
263 Future<HierarchyResults> typeHierarchyTest(String text) { | |
264 int offset = text.indexOf(' /* target */') - 1; | |
265 sendAnalysisUpdateContent({ | |
266 pathname: { | |
267 'type': 'add', | |
268 'content': text | |
269 } | |
270 }); | |
271 return analysisFinished.then((_) => sendSearchGetTypeHierarchy(pathname, | |
272 offset)).then((result) { | |
273 if (result.isEmpty) { | |
274 return null; | |
275 } else { | |
276 return new HierarchyResults(result); | |
277 } | |
278 }); | |
279 } | |
280 } | |
281 | |
282 main() { | |
283 runReflectiveTests(SearchDomainIntegrationTest); | |
284 } | |
OLD | NEW |