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 /// Common test code that is run by 3 tests: mirrors_test.dart, | |
6 /// mirrors_used_test.dart, and static_test.dart. | |
7 library smoke.test.common; | |
8 | |
9 import 'package:smoke/smoke.dart' as smoke; | |
10 import 'package:test/test.dart'; | |
11 | |
12 main() { | |
13 test('read value', () { | |
14 var a = new A(); | |
15 expect(smoke.read(a, #i), 42); | |
16 expect(smoke.read(a, #j), 44); | |
17 expect(smoke.read(a, #j2), 44); | |
18 }); | |
19 | |
20 test('write value', () { | |
21 var a = new A(); | |
22 smoke.write(a, #i, 43); | |
23 expect(a.i, 43); | |
24 smoke.write(a, #j2, 46); | |
25 expect(a.j, 46); | |
26 expect(a.j2, 46); | |
27 expect(smoke.read(a, #j), 46); | |
28 expect(smoke.read(a, #j2), 46); | |
29 }); | |
30 | |
31 test('invoke', () { | |
32 var a = new A(); | |
33 | |
34 smoke.invoke(a, #inc0, []); | |
35 expect(a.i, 43); | |
36 expect(smoke.read(a, #i), 43); | |
37 expect(() => smoke.invoke(a, #inc0, [2]), throws); | |
38 expect(a.i, 43); | |
39 expect(() => smoke.invoke(a, #inc0, [1, 2, 3]), throws); | |
40 expect(a.i, 43); | |
41 | |
42 // TODO(jakemac): Restore this once http://dartbug.com/22917 is fixed. | |
43 // expect(() => smoke.invoke(a, #inc1, []), throws); | |
44 expect(a.i, 43); | |
45 smoke.invoke(a, #inc1, [4]); | |
46 expect(a.i, 47); | |
47 | |
48 smoke.invoke(a, #inc2, []); | |
49 expect(a.i, 37); | |
50 smoke.invoke(a, #inc2, [4]); | |
51 expect(a.i, 41); | |
52 | |
53 expect(() => smoke.invoke(a, #inc1, [4, 5]), throws); | |
54 expect(a.i, 41); | |
55 }); | |
56 | |
57 test('static invoke', () { | |
58 A.staticValue = 42; | |
59 smoke.invoke(A, #staticInc, []); | |
60 expect(A.staticValue, 43); | |
61 }); | |
62 | |
63 test('read and invoke function', () { | |
64 var a = new A(); | |
65 expect(a.i, 42); | |
66 var f = smoke.read(a, #inc1); | |
67 f(4); | |
68 expect(a.i, 46); | |
69 Function.apply(f, [4]); | |
70 expect(a.i, 50); | |
71 }); | |
72 | |
73 test('invoke with adjust', () { | |
74 var a = new A(); | |
75 smoke.invoke(a, #inc0, [], adjust: true); | |
76 expect(a.i, 43); | |
77 smoke.invoke(a, #inc0, [2], adjust: true); | |
78 expect(a.i, 44); | |
79 smoke.invoke(a, #inc0, [1, 2, 3], adjust: true); | |
80 expect(a.i, 45); | |
81 | |
82 smoke.invoke(a, #inc1, [], adjust: true); // treat as null (-10) | |
83 expect(a.i, 35); | |
84 smoke.invoke(a, #inc1, [4], adjust: true); | |
85 expect(a.i, 39); | |
86 | |
87 smoke.invoke(a, #inc2, [], adjust: true); // default is null (-10) | |
88 expect(a.i, 29); | |
89 smoke.invoke(a, #inc2, [4, 5], adjust: true); | |
90 expect(a.i, 33); | |
91 }); | |
92 | |
93 test('has getter', () { | |
94 expect(smoke.hasGetter(A, #i), isTrue); | |
95 expect(smoke.hasGetter(A, #j2), isTrue); | |
96 expect(smoke.hasGetter(A, #inc2), isTrue); | |
97 expect(smoke.hasGetter(B, #a), isTrue); | |
98 expect(smoke.hasGetter(B, #i), isFalse); | |
99 expect(smoke.hasGetter(B, #f), isTrue); | |
100 expect(smoke.hasGetter(D, #i), isTrue); | |
101 | |
102 expect(smoke.hasGetter(E, #x), isFalse); | |
103 expect(smoke.hasGetter(E, #y), isTrue); | |
104 expect(smoke.hasGetter(E, #z), isFalse); // don't consider noSuchMethod | |
105 }); | |
106 | |
107 test('has setter', () { | |
108 expect(smoke.hasSetter(A, #i), isTrue); | |
109 expect(smoke.hasSetter(A, #j2), isTrue); | |
110 expect(smoke.hasSetter(A, #inc2), isFalse); | |
111 expect(smoke.hasSetter(B, #a), isTrue); | |
112 expect(smoke.hasSetter(B, #i), isFalse); | |
113 expect(smoke.hasSetter(B, #f), isFalse); | |
114 expect(smoke.hasSetter(D, #i), isTrue); | |
115 | |
116 // TODO(sigmund): should we support declaring a setter with no getter? | |
117 // expect(smoke.hasSetter(E, #x), isTrue); | |
118 expect(smoke.hasSetter(E, #y), isFalse); | |
119 expect(smoke.hasSetter(E, #z), isFalse); // don't consider noSuchMethod | |
120 }); | |
121 | |
122 test('no such method', () { | |
123 expect(smoke.hasNoSuchMethod(A), isFalse); | |
124 expect(smoke.hasNoSuchMethod(E), isTrue); | |
125 expect(smoke.hasNoSuchMethod(E2), isTrue); | |
126 expect(smoke.hasNoSuchMethod(int), isFalse); | |
127 }); | |
128 | |
129 test('has instance method', () { | |
130 expect(smoke.hasInstanceMethod(A, #inc0), isTrue); | |
131 expect(smoke.hasInstanceMethod(A, #inc3), isFalse); | |
132 expect(smoke.hasInstanceMethod(C, #inc), isTrue); | |
133 expect(smoke.hasInstanceMethod(D, #inc), isTrue); | |
134 expect(smoke.hasInstanceMethod(D, #inc0), isTrue); | |
135 expect(smoke.hasInstanceMethod(F, #staticMethod), isFalse); | |
136 expect(smoke.hasInstanceMethod(F2, #staticMethod), isFalse); | |
137 }); | |
138 | |
139 test('has static method', () { | |
140 expect(smoke.hasStaticMethod(A, #inc0), isFalse); | |
141 expect(smoke.hasStaticMethod(C, #inc), isFalse); | |
142 expect(smoke.hasStaticMethod(D, #inc), isFalse); | |
143 expect(smoke.hasStaticMethod(D, #inc0), isFalse); | |
144 expect(smoke.hasStaticMethod(F, #staticMethod), isTrue); | |
145 expect(smoke.hasStaticMethod(F2, #staticMethod), isFalse); | |
146 }); | |
147 | |
148 test('get declaration', () { | |
149 var d = smoke.getDeclaration(B, #a); | |
150 expect(d.name, #a); | |
151 expect(d.isField, isTrue); | |
152 expect(d.isProperty, isFalse); | |
153 expect(d.isMethod, isFalse); | |
154 expect(d.isFinal, isFalse); | |
155 expect(d.isStatic, isFalse); | |
156 expect(d.annotations, []); | |
157 expect(d.type, A); | |
158 | |
159 d = smoke.getDeclaration(B, #w); | |
160 expect(d.name, #w); | |
161 expect(d.isField, isFalse); | |
162 expect(d.isProperty, isTrue); | |
163 expect(d.isMethod, isFalse); | |
164 expect(d.isFinal, isFalse); | |
165 expect(d.isStatic, isFalse); | |
166 expect(d.annotations, []); | |
167 expect(d.type, int); | |
168 | |
169 d = smoke.getDeclaration(A, #inc1); | |
170 expect(d.name, #inc1); | |
171 expect(d.isField, isFalse); | |
172 expect(d.isProperty, isFalse); | |
173 expect(d.isMethod, isTrue); | |
174 expect(d.isFinal, isFalse); | |
175 expect(d.isStatic, isFalse); | |
176 expect(d.annotations, []); | |
177 expect(d.type, Function); | |
178 | |
179 d = smoke.getDeclaration(F, #staticMethod); | |
180 expect(d.name, #staticMethod); | |
181 expect(d.isField, isFalse); | |
182 expect(d.isProperty, isFalse); | |
183 expect(d.isMethod, isTrue); | |
184 expect(d.isFinal, isFalse); | |
185 expect(d.isStatic, isTrue); | |
186 expect(d.annotations, []); | |
187 expect(d.type, Function); | |
188 | |
189 d = smoke.getDeclaration(G, #b); | |
190 expect(d.name, #b); | |
191 expect(d.isField, isTrue); | |
192 expect(d.isProperty, isFalse); | |
193 expect(d.isMethod, isFalse); | |
194 expect(d.isFinal, isFalse); | |
195 expect(d.isStatic, isFalse); | |
196 expect(d.annotations, [const Annot()]); | |
197 expect(d.type, int); | |
198 | |
199 d = smoke.getDeclaration(G, #d); | |
200 expect(d.name, #d); | |
201 expect(d.isField, isTrue); | |
202 expect(d.isProperty, isFalse); | |
203 expect(d.isMethod, isFalse); | |
204 expect(d.isFinal, isFalse); | |
205 expect(d.isStatic, isFalse); | |
206 expect(d.annotations, [32]); | |
207 expect(d.type, int); | |
208 }); | |
209 | |
210 test('isSuperclass', () { | |
211 expect(smoke.isSubclassOf(D, C), isTrue); | |
212 expect(smoke.isSubclassOf(H, G), isTrue); | |
213 expect(smoke.isSubclassOf(H, H), isTrue); | |
214 expect(smoke.isSubclassOf(H, Object), isTrue); | |
215 expect(smoke.isSubclassOf(B, Object), isTrue); | |
216 expect(smoke.isSubclassOf(A, Object), isTrue); | |
217 expect(smoke.isSubclassOf(AnnotB, Annot), isTrue); | |
218 | |
219 expect(smoke.isSubclassOf(D, A), isFalse); | |
220 expect(smoke.isSubclassOf(H, B), isFalse); | |
221 expect(smoke.isSubclassOf(B, A), isFalse); | |
222 expect(smoke.isSubclassOf(Object, A), isFalse); | |
223 }); | |
224 | |
225 group('query', () { | |
226 _checkQuery(result, names) { | |
227 expect(result.map((e) => e.name), unorderedEquals(names)); | |
228 } | |
229 | |
230 test('default', () { | |
231 var options = new smoke.QueryOptions(); | |
232 var res = smoke.query(A, options); | |
233 _checkQuery(res, [#i, #j, #j2]); | |
234 }); | |
235 | |
236 test('only fields', () { | |
237 var options = new smoke.QueryOptions(includeProperties: false); | |
238 var res = smoke.query(A, options); | |
239 _checkQuery(res, [#i, #j]); | |
240 expect(res[0].isField, true); | |
241 }); | |
242 | |
243 test('only properties', () { | |
244 var options = new smoke.QueryOptions(includeFields: false); | |
245 var res = smoke.query(A, options); | |
246 _checkQuery(res, [#j2]); | |
247 expect(res[0].isProperty, true); | |
248 }); | |
249 | |
250 test('properties and methods', () { | |
251 var options = new smoke.QueryOptions(includeMethods: true); | |
252 var res = smoke.query(A, options); | |
253 _checkQuery(res, [#i, #j, #j2, #inc0, #inc1, #inc2]); | |
254 }); | |
255 | |
256 test('inherited properties and fields', () { | |
257 var options = new smoke.QueryOptions(includeInherited: true); | |
258 var res = smoke.query(D, options); | |
259 _checkQuery(res, [#x, #y, #b, #i, #j, #j2, #x2, #i2]); | |
260 }); | |
261 | |
262 test('inherited fields only', () { | |
263 var options = new smoke.QueryOptions( | |
264 includeInherited: true, includeProperties: false); | |
265 var res = smoke.query(D, options); | |
266 _checkQuery(res, [#x, #y, #b, #i, #j]); | |
267 }); | |
268 | |
269 test('exact annotation', () { | |
270 var options = new smoke.QueryOptions( | |
271 includeInherited: true, withAnnotations: const [a1]); | |
272 var res = smoke.query(H, options); | |
273 _checkQuery(res, [#b, #f, #g]); | |
274 | |
275 options = new smoke.QueryOptions( | |
276 includeInherited: true, withAnnotations: const [a2]); | |
277 res = smoke.query(H, options); | |
278 _checkQuery(res, [#d, #h]); | |
279 | |
280 options = new smoke.QueryOptions( | |
281 includeInherited: true, withAnnotations: const [a1, a2]); | |
282 res = smoke.query(H, options); | |
283 _checkQuery(res, [#b, #d, #f, #g, #h]); | |
284 }); | |
285 | |
286 test('type annotation', () { | |
287 var options = new smoke.QueryOptions( | |
288 includeInherited: true, withAnnotations: const [Annot]); | |
289 var res = smoke.query(H, options); | |
290 _checkQuery(res, [#b, #f, #g, #i]); | |
291 }); | |
292 | |
293 test('mixed annotations (type and exact)', () { | |
294 var options = new smoke.QueryOptions( | |
295 includeInherited: true, withAnnotations: const [a2, Annot]); | |
296 var res = smoke.query(H, options); | |
297 _checkQuery(res, [#b, #d, #f, #g, #h, #i]); | |
298 }); | |
299 | |
300 test('overriden symbols', () { | |
301 var options = new smoke.QueryOptions( | |
302 excludeOverriden: true, includeInherited: true, includeMethods: true); | |
303 var res = smoke.query(L2, options); | |
304 _checkQuery(res, [#m, #incM, #n]); | |
305 // Check that the concrete #m is there | |
306 var overriden = res.firstWhere((value) => value.name == #m); | |
307 expect(overriden.isFinal, false); | |
308 expect(overriden.isField, true); | |
309 }); | |
310 | |
311 test('symbol to name', () { | |
312 expect(smoke.symbolToName(#i), 'i'); | |
313 }); | |
314 | |
315 test('name to symbol', () { | |
316 expect(smoke.nameToSymbol('i'), #i); | |
317 }); | |
318 }); | |
319 | |
320 test('invoke Type instance methods', () { | |
321 var a = new A(); | |
322 expect( | |
323 smoke.invoke(a.runtimeType, #toString, []), a.runtimeType.toString()); | |
324 }); | |
325 } | |
326 | |
327 class A { | |
328 int i = 42; | |
329 int j = 44; | |
330 int get j2 => j; | |
331 void set j2(int v) { | |
332 j = v; | |
333 } | |
334 void inc0() { | |
335 i++; | |
336 } | |
337 void inc1(int v) { | |
338 i = i + (v == null ? -10 : v); | |
339 } | |
340 void inc2([int v]) { | |
341 i = i + (v == null ? -10 : v); | |
342 } | |
343 | |
344 static int staticValue = 42; | |
345 static void staticInc() { | |
346 staticValue++; | |
347 } | |
348 } | |
349 | |
350 class B { | |
351 final int f = 3; | |
352 int _w; | |
353 int get w => _w; | |
354 set w(int v) { | |
355 _w = v; | |
356 } | |
357 | |
358 String z; | |
359 A a; | |
360 | |
361 B(this._w, this.z, this.a); | |
362 } | |
363 | |
364 class C { | |
365 int x; | |
366 String y; | |
367 B b; | |
368 | |
369 inc(int n) { | |
370 x = x + n; | |
371 } | |
372 dec(int n) { | |
373 x = x - n; | |
374 } | |
375 | |
376 C(this.x, this.y, this.b); | |
377 } | |
378 | |
379 class D extends C with A { | |
380 int get x2 => x; | |
381 int get i2 => i; | |
382 | |
383 D(x, y, b) : super(x, y, b); | |
384 } | |
385 | |
386 class E { | |
387 set x(int v) {} | |
388 int get y => 1; | |
389 | |
390 noSuchMethod(i) => y; | |
391 } | |
392 | |
393 class E2 extends E {} | |
394 | |
395 class F { | |
396 static int staticMethod(A a) => a.i; | |
397 } | |
398 | |
399 class F2 extends F {} | |
400 | |
401 class Annot { | |
402 const Annot(); | |
403 } | |
404 class AnnotB extends Annot { | |
405 const AnnotB(); | |
406 } | |
407 class AnnotC { | |
408 const AnnotC({bool named: false}); | |
409 } | |
410 const a1 = const Annot(); | |
411 const a2 = 32; | |
412 const a3 = const AnnotB(); | |
413 | |
414 class G { | |
415 int a; | |
416 @a1 int b; | |
417 int c; | |
418 @a2 int d; | |
419 } | |
420 | |
421 class H extends G { | |
422 int e; | |
423 @a1 int f; | |
424 @a1 int g; | |
425 @a2 int h; | |
426 @a3 int i; | |
427 } | |
428 | |
429 class K { | |
430 @AnnotC(named: true) int k; | |
431 @AnnotC() int k2; | |
432 } | |
433 | |
434 abstract class L { | |
435 int get m; | |
436 incM(); | |
437 } | |
438 | |
439 class L2 extends L { | |
440 int m; | |
441 incM() { ++m; } | |
442 int n; | |
443 } | |
OLD | NEW |