OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, 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 // Test code | |
6 import 'dart:collection'; | |
7 import 'dart:mirrors'; | |
8 import 'package:test/test.dart'; | |
9 import 'package:dev_compiler/config.dart'; | |
10 import 'package:dev_compiler/runtime/dart_runtime.dart'; | |
11 | |
12 final bool intIsNonNullable = TypeOptions.NONNULLABLE_TYPES.contains('int'); | |
13 final bool doubleIsNonNullable = | |
14 TypeOptions.NONNULLABLE_TYPES.contains('double'); | |
15 | |
16 class A { | |
17 int x; | |
18 } | |
19 | |
20 class B extends A { | |
21 int y; | |
22 } | |
23 | |
24 class C extends B { | |
25 int z; | |
26 } | |
27 | |
28 class AA<T, U> { | |
29 T x; | |
30 U y; | |
31 } | |
32 | |
33 class BB<T, U> extends AA<U, T> { | |
34 T z; | |
35 } | |
36 | |
37 class CC extends BB<String, List> {} | |
38 | |
39 typedef Func2(x, y); | |
40 typedef B Foo(B b, String s); | |
41 | |
42 A bar1(C c, String s) => null; | |
43 bar2(B b, String s) => null; | |
44 B bar3(B b, Object o) => null; | |
45 B bar4(B b, o) => null; | |
46 C bar5(A a, Object o) => null; | |
47 B bar6(B b, String s, String o) => null; | |
48 B bar7(B b, String s, [Object o]) => null; | |
49 B bar8(B b, String s, {Object p}) => null; | |
50 | |
51 class Bar { | |
52 B call(B b, String s) => null; | |
53 } | |
54 | |
55 class Baz { | |
56 Foo call = (B b, String s) => null; | |
57 } | |
58 | |
59 class Checker<T> { | |
60 void isGround(bool expected) => expect(isGroundType(T), equals(expected)); | |
61 void isGroundList(bool expected) => | |
62 expect(isGroundType(new List<T>().runtimeType), equals(expected)); | |
63 void check(x, bool expected) => checkType(x, T, expected); | |
64 void checkList(x, bool expected) => | |
65 checkType(x, type((List<T> _) {}), expected); | |
66 } | |
67 | |
68 bool dartIs(expr, Type type) { | |
69 var exprMirror = reflectType(expr.runtimeType); | |
70 var typeMirror = reflectType(type); | |
71 return exprMirror.isSubtypeOf(typeMirror); | |
72 } | |
73 | |
74 void checkType(x, Type type, [bool expectedTrue = true]) { | |
75 var isGround = isGroundType(type); | |
76 var restrictedSubType = instanceOf(x, type); | |
77 var dartSubType = dartIs(x, type); | |
78 | |
79 // Matches expectation | |
80 expect(restrictedSubType, equals(expectedTrue)); | |
81 | |
82 // x is_R T => x is T | |
83 expect(!restrictedSubType || dartSubType, isTrue); | |
84 | |
85 // x is T && isGroundType(T) => x is_R T | |
86 expect(!(dartSubType && isGround) || restrictedSubType, isTrue); | |
87 } | |
88 | |
89 void checkArity(Function f, int min, int max) { | |
90 Arity arity = getArity(f); | |
91 expect(arity.min, equals(min)); | |
92 expect(arity.max, equals(max)); | |
93 } | |
94 | |
95 void main() { | |
96 test('int', () { | |
97 expect(isGroundType(int), isTrue); | |
98 expect(isGroundType(5.runtimeType), isTrue); | |
99 | |
100 checkType(5, int); | |
101 checkType(5, dynamic); | |
102 checkType(5, Object); | |
103 checkType(5, num); | |
104 | |
105 checkType(5, bool, false); | |
106 checkType(5, String, false); | |
107 | |
108 expect(cast(5, int), equals(5)); | |
109 if (intIsNonNullable) { | |
110 expect(() => cast(null, int), throws); | |
111 } else { | |
112 expect(cast(null, int), equals(null)); | |
113 } | |
114 }); | |
115 | |
116 test('dynamic', () { | |
117 expect(isGroundType(dynamic), isTrue); | |
118 checkType(new Object(), dynamic); | |
119 checkType(null, dynamic); | |
120 | |
121 expect(cast(null, dynamic), equals(null)); | |
122 }); | |
123 | |
124 test('Object', () { | |
125 expect(isGroundType(Object), isTrue); | |
126 checkType(new Object(), dynamic); | |
127 checkType(null, Object); | |
128 | |
129 expect(cast(null, Object), equals(null)); | |
130 }); | |
131 | |
132 test('String', () { | |
133 expect(isGroundType(String), isTrue); | |
134 expect(isGroundType("foo".runtimeType), isTrue); | |
135 checkType("foo", String); | |
136 checkType("foo", Object); | |
137 checkType("foo", dynamic); | |
138 | |
139 expect(cast(null, String), equals(null)); | |
140 }); | |
141 | |
142 test('Map', () { | |
143 final m1 = new Map<String, String>(); | |
144 final m2 = new Map<Object, Object>(); | |
145 final m3 = new Map(); | |
146 final m4 = new HashMap<dynamic, dynamic>(); | |
147 final m5 = new LinkedHashMap(); | |
148 | |
149 expect(isGroundType(Map), isTrue); | |
150 expect(isGroundType(m1.runtimeType), isFalse); | |
151 expect(isGroundType(type((Map<String, String> _) {})), isFalse); | |
152 expect(isGroundType(m2.runtimeType), isTrue); | |
153 expect(isGroundType(type((Map<Object, Object> _) {})), isTrue); | |
154 expect(isGroundType(m3.runtimeType), isTrue); | |
155 expect(isGroundType(type((Map _) {})), isTrue); | |
156 expect(isGroundType(m4.runtimeType), isTrue); | |
157 expect(isGroundType(type((HashMap<dynamic, dynamic> _) {})), isTrue); | |
158 expect(isGroundType(m5.runtimeType), isTrue); | |
159 expect(isGroundType(type((LinkedHashMap _) {})), isTrue); | |
160 expect(isGroundType(LinkedHashMap), isTrue); | |
161 | |
162 // Map<T1,T2> <: Map | |
163 checkType(m1, Map); | |
164 checkType(m1, Object); | |
165 | |
166 // Instance of self | |
167 checkType(m1, m1.runtimeType); | |
168 checkType(m1, type((Map<String, String> _) {})); | |
169 | |
170 // Object == dynamic == top as a type parameter | |
171 checkType(m2, m3.runtimeType); | |
172 checkType(m2, Map); | |
173 checkType(m3, m2.runtimeType); | |
174 checkType(m3, type((Map<Object, Object> _) {})); | |
175 | |
176 // Covariance on generics | |
177 checkType(m1, m2.runtimeType); | |
178 checkType(m1, type((Map<Object, Object> _) {})); | |
179 | |
180 // No contravariance on generics. | |
181 checkType(m2, m1.runtimeType, false); | |
182 checkType(m2, type((Map<String, String> _) {}), false); | |
183 | |
184 // null is! Map | |
185 checkType(null, Map, false); | |
186 | |
187 // Raw generic types | |
188 checkType(m5, Map); | |
189 checkType(m5, type((Map<Object, Object> _) {})); | |
190 checkType(m4, Map); | |
191 checkType(m4, type((Map<Object, Object> _) {})); | |
192 | |
193 // Mixin: the actual implementation class should implement MapMixin | |
194 checkType(m1, MapMixin); | |
195 checkType(m1, type((MapMixin<String, String> _) {})); | |
196 checkType(m1, type((MapMixin<Object, Object> _) {})); | |
197 checkType(m5, MapMixin); | |
198 checkType(m5, type((MapMixin<String, String> _) {}), false); | |
199 checkType(m5, type((MapMixin<Object, Object> _) {})); | |
200 }); | |
201 | |
202 test('generic and inheritance', () { | |
203 AA aaraw = new AA(); | |
204 final aarawtype = aaraw.runtimeType; | |
205 AA<dynamic, dynamic> aadynamic = new AA<dynamic, dynamic>(); | |
206 final aadynamictype = aadynamic.runtimeType; | |
207 AA<String, List> aa = new AA<String, List>(); | |
208 final aatype = aa.runtimeType; | |
209 BB<String, List> bb = new BB<String, List>(); | |
210 final bbtype = bb.runtimeType; | |
211 CC cc = new CC(); | |
212 final cctype = cc.runtimeType; | |
213 AA<String> aabad = new AA<String>(); | |
214 final aabadtype = aabad.runtimeType; | |
215 | |
216 expect(isGroundType(aatype), isFalse); | |
217 expect(isGroundType(type((AA<String, List> _) {})), isFalse); | |
218 expect(isGroundType(bbtype), isFalse); | |
219 expect(isGroundType(type((BB<String, List> _) {})), isFalse); | |
220 expect(isGroundType(cctype), isTrue); | |
221 expect(isGroundType(CC), isTrue); | |
222 checkType(cc, aatype, false); | |
223 checkType(cc, type((AA<String, List> _) {}), false); | |
224 checkType(cc, bbtype); | |
225 checkType(cc, type((BB<String, List> _) {})); | |
226 checkType(aa, cctype, false); | |
227 checkType(aa, CC, false); | |
228 checkType(aa, bbtype, false); | |
229 checkType(aa, type((BB<String, List> _) {}), false); | |
230 checkType(bb, cctype, false); | |
231 checkType(bb, CC, false); | |
232 checkType(aa, aabadtype); | |
233 checkType(aa, type((AA<String> _) {})); | |
234 checkType(aabad, aatype, false); | |
235 checkType(aabad, type((AA<String, List> _) {}), false); | |
236 checkType(aabad, aarawtype); | |
237 checkType(aabad, AA); | |
238 checkType(aaraw, aabadtype); | |
239 checkType(aaraw, type((AA<String> _) {})); | |
240 checkType(aaraw, aadynamictype); | |
241 checkType(aaraw, type((AA<dynamic, dynamic> _) {})); | |
242 checkType(aadynamic, aarawtype); | |
243 checkType(aadynamic, AA); | |
244 }); | |
245 | |
246 test('Functions', () { | |
247 // - return type: Dart is bivariant. We're covariant. | |
248 // - param types: Dart is bivariant. We're contravariant. | |
249 expect(isGroundType(Func2), isTrue); | |
250 expect(isGroundType(Foo), isFalse); | |
251 expect(isGroundType(type((B _(B _1, String _2)) {})), isFalse); | |
252 checkType(bar1, Foo, false); | |
253 checkType(bar1, type((B _(B _1, String _2)) {}), false); | |
254 checkType(bar2, Foo, false); | |
255 checkType(bar2, type((B _(B _1, String _2)) {}), false); | |
256 checkType(bar3, Foo); | |
257 checkType(bar3, type((B _(B _1, String _2)) {})); | |
258 checkType(bar4, Foo, false); | |
259 // TODO(vsm): Revisit. bar4 is (B, *) -> B. Perhaps it should be treated a
s top for a reified object. | |
260 checkType(bar4, type((B _(B _1, String _2)) {}), false); | |
261 checkType(bar5, Foo); | |
262 checkType(bar5, type((B _(B _1, String _2)) {})); | |
263 checkType(bar6, Foo, false); | |
264 checkType(bar6, type((B _(B _1, String _2)) {}), false); | |
265 checkType(bar7, Foo); | |
266 checkType(bar7, type((B _(B _1, String _2)) {})); | |
267 checkType(bar7, bar6.runtimeType); | |
268 checkType(bar8, Foo); | |
269 checkType(bar8, type((B _(B _1, String _2)) {})); | |
270 checkType(bar8, bar6.runtimeType, false); | |
271 checkType(bar7, bar8.runtimeType, false); | |
272 checkType(bar8, bar7.runtimeType, false); | |
273 }); | |
274 | |
275 test('void', () { | |
276 checkType((x) => x, type((void _(x)) {})); | |
277 }); | |
278 | |
279 test('null', () { | |
280 checkType(null, Object); | |
281 checkType(null, Null); | |
282 checkType(null, dynamic); | |
283 checkType(null, int, false); | |
284 checkType(null, String, false); | |
285 checkType(null, Map, false); | |
286 | |
287 expect(cast(null, Object), equals(null)); | |
288 expect(cast(null, String), equals(null)); | |
289 expect(cast(null, Map), equals(null)); | |
290 }); | |
291 | |
292 test('Function objects', () { | |
293 // Bar has a call method - it emulates the corresponding function. | |
294 var bar = new Bar(); | |
295 checkType(bar, Bar); | |
296 checkType(bar, Function); | |
297 checkType(bar, Foo); | |
298 checkType(bar, type((B _(B _1, String _2)) {})); | |
299 checkType(bar, type((B _(String _1, String _2)) {}), false); | |
300 | |
301 // Baz has a call getter that is a closure - this does not make it a | |
302 // function. | |
303 var baz = new Baz(); | |
304 checkType(baz, Function, false); | |
305 checkType(baz, Foo, false); | |
306 }); | |
307 | |
308 test('arity', () { | |
309 checkArity(bar1, 2, 2); | |
310 checkArity(bar4, 2, 2); | |
311 checkArity(bar6, 3, 3); | |
312 checkArity(bar7, 2, 3); | |
313 checkArity(bar8, 2, 2); | |
314 checkArity(() {}, 0, 0); | |
315 checkArity((a, [b]) {}, 1, 2); | |
316 }); | |
317 | |
318 test('type variable', () { | |
319 var stringChecker = new Checker<String>(); | |
320 stringChecker.isGround(true); | |
321 stringChecker.isGroundList(false); | |
322 | |
323 stringChecker.check(5, false); | |
324 stringChecker.check("hello", true); | |
325 stringChecker.check(null, false); | |
326 | |
327 var objectChecker = new Checker<Object>(); | |
328 objectChecker.isGround(true); | |
329 objectChecker.isGroundList(true); | |
330 | |
331 objectChecker.check(5, true); | |
332 objectChecker.check("hello", true); | |
333 objectChecker.check(null, true); | |
334 }); | |
335 } | |
OLD | NEW |