| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library MirrorsTest; | 5 import 'dart:mirrors'; |
| 6 import 'package:expect/expect.dart'; |
| 7 import 'stringify.dart'; |
| 6 | 8 |
| 7 import 'dart:mirrors'; | 9 testIntercepted() { |
| 8 | 10 var instance = []; |
| 9 import '../../light_unittest.dart'; | 11 var methodMirror = reflect(instance.toString); |
| 10 | 12 String rest = ' in s(List)'; |
| 11 bool isDart2js = false; // TODO(ahe): Remove this field. | 13 rest = ''; /// 01: ok |
| 12 | 14 expect('Method(s(toString)$rest)', methodMirror.function); |
| 13 var topLevelField; | 15 Expect.equals('[]', methodMirror.apply([]).reflectee); |
| 14 u(a, b, c) => {"a": a, "b": b, "c": c}; | |
| 15 _v(a, b) => a + b; | |
| 16 | |
| 17 class Class<T> { | |
| 18 Class() { this.field = "default value"; } | |
| 19 Class.withInitialValue(this.field); | |
| 20 var field; | |
| 21 | |
| 22 Class.generative(this.field); | |
| 23 Class.redirecting(y) : this.generative(y*2); | |
| 24 factory Class.faktory(y) => new Class.withInitialValue(y*3); | |
| 25 factory Class.redirectingFactory(y) = Class.faktory; | |
| 26 | |
| 27 m(a, b, c) => {"a": a, "b": b, "c": c}; | |
| 28 _n(a, b) => a + b; | |
| 29 noSuchMethod(invocation) => "DNU"; | |
| 30 | |
| 31 static var staticField; | |
| 32 static s(a, b, c) => {"a": a, "b": b, "c": c}; | |
| 33 static _t(a, b) => a + b; | |
| 34 } | 16 } |
| 35 | 17 |
| 36 typedef Typedef(); | 18 testNonIntercepted() { |
| 37 | 19 var closure = new Map().containsKey; |
| 38 testInvoke(mirrors) { | |
| 39 var instance = new Class(); | |
| 40 var instMirror = reflect(instance); | |
| 41 | |
| 42 expect(instMirror.invoke(const Symbol("m"),['A', 'B', instance]).reflectee, | |
| 43 equals({"a": 'A', "b":'B', "c": instance})); | |
| 44 expect(instMirror.invoke(const Symbol("notDefined"), []).reflectee, | |
| 45 equals("DNU")); | |
| 46 expect(instMirror.invoke(const Symbol("m"), []).reflectee, | |
| 47 equals("DNU")); // Wrong arity. | |
| 48 // TODO(rmacnak): Implement access to private members. | |
| 49 // expect(instMirror.invoke(const Symbol("_n"), [3, 4]).reflectee, | |
| 50 // equals(7)); | |
| 51 | |
| 52 var classMirror = instMirror.type; | |
| 53 expect(classMirror.invoke(const Symbol("s"),['A', 'B', instance]).reflectee, | |
| 54 equals({"a": 'A', "b":'B', "c": instance})); | |
| 55 expect(() => classMirror.invoke(const Symbol("notDefined"), []).reflectee, | |
| 56 throws); | |
| 57 expect(() => classMirror.invoke(const Symbol("s"), []).reflectee, | |
| 58 throws); // Wrong arity. | |
| 59 // TODO(rmacnak): Implement access to private members. | |
| 60 // expect(classMirror.invoke(const Symbol("_t"), [3, 4]).reflectee, | |
| 61 // equals(7)); | |
| 62 | |
| 63 var libMirror = classMirror.owner; | |
| 64 expect(libMirror.invoke(const Symbol("u"),['A', 'B', instance]).reflectee, | |
| 65 equals({"a": 'A', "b":'B', "c": instance})); | |
| 66 expect(() => libMirror.invoke(const Symbol("notDefined"), []).reflectee, | |
| 67 throws); | |
| 68 expect(() => libMirror.invoke(const Symbol("u"), []).reflectee, | |
| 69 throws); // Wrong arity. | |
| 70 // NB: This works on the VM but fails at compile-time on dart2js. | |
| 71 // expect(libMirror.invoke(const Symbol("_v"), [3, 4]).reflectee, | |
| 72 // equals(7)); | |
| 73 } | |
| 74 | |
| 75 testInstanceFieldAccess(mirrors) { | |
| 76 var instance = new Class(); | |
| 77 var instMirror = reflect(instance); | |
| 78 | |
| 79 instMirror.setFieldAsync(const Symbol('field'), 44); | |
| 80 instMirror.getFieldAsync(const Symbol('field')).then( | |
| 81 expectAsync1((resultMirror) { | |
| 82 expect(resultMirror.reflectee, equals(44)); | |
| 83 expect(instance.field, equals(44)); | |
| 84 })); | |
| 85 } | |
| 86 | |
| 87 /// In dart2js, lists, numbers, and other objects are treated special | |
| 88 /// and their methods are invoked through a techique called interceptors. | |
| 89 testIntercepted(mirrors) { | |
| 90 var instance = 1; | |
| 91 var instMirror = reflect(instance); | |
| 92 | |
| 93 expect(instMirror.invoke(const Symbol('toString'), []).reflectee, | |
| 94 equals('1')); | |
| 95 | |
| 96 instance = []; | |
| 97 instMirror = reflect(instance); | |
| 98 instMirror.setField(const Symbol('length'), 44); | |
| 99 var resultMirror = instMirror.getField(const Symbol('length')); | |
| 100 expect(resultMirror.reflectee, equals(44)); | |
| 101 expect(instance.length, equals(44)); | |
| 102 | |
| 103 expect(instMirror.invoke(const Symbol('toString'), []).reflectee, | |
| 104 equals('[null, null, null, null, null, null, null, null, null, null,' | |
| 105 ' null, null, null, null, null, null, null, null, null, null,' | |
| 106 ' null, null, null, null, null, null, null, null, null, null,' | |
| 107 ' null, null, null, null, null, null, null, null, null, null,' | |
| 108 ' null, null, null, null]')); | |
| 109 } | |
| 110 | |
| 111 testFieldAccess(mirrors) { | |
| 112 var instance = new Class(); | |
| 113 | |
| 114 var libMirror = mirrors.findLibrary(const Symbol("MirrorsTest")).single; | |
| 115 var classMirror = libMirror.classes[const Symbol("Class")]; | |
| 116 var instMirror = reflect(instance); | |
| 117 var fieldMirror = classMirror.members[const Symbol('field')]; | |
| 118 var future; | |
| 119 | |
| 120 expect(fieldMirror is VariableMirror, isTrue); | |
| 121 expect(fieldMirror.type, equals(mirrors.dynamicType)); | |
| 122 | |
| 123 libMirror.setField(const Symbol('topLevelField'), [91]); | |
| 124 expect(libMirror.getField(const Symbol('topLevelField')).reflectee, | |
| 125 equals([91])); | |
| 126 expect(topLevelField, equals([91])); | |
| 127 | |
| 128 libMirror.setFieldAsync(const Symbol('topLevelField'), 42); | |
| 129 future = libMirror.getFieldAsync(const Symbol('topLevelField')); | |
| 130 future.then(expectAsync1((resultMirror) { | |
| 131 expect(resultMirror.reflectee, equals(42)); | |
| 132 expect(topLevelField, equals(42)); | |
| 133 })); | |
| 134 | |
| 135 classMirror.setFieldAsync(const Symbol('staticField'), 43); | |
| 136 future = classMirror.getFieldAsync(const Symbol('staticField')); | |
| 137 future.then(expectAsync1((resultMirror) { | |
| 138 expect(resultMirror.reflectee, equals(43)); | |
| 139 expect(Class.staticField, equals(43)); | |
| 140 })); | |
| 141 | |
| 142 instMirror.setFieldAsync(const Symbol('field'), 44); | |
| 143 future = instMirror.getFieldAsync(const Symbol('field')); | |
| 144 future.then(expectAsync1((resultMirror) { | |
| 145 expect(resultMirror.reflectee, equals(44)); | |
| 146 expect(instance.field, equals(44)); | |
| 147 })); | |
| 148 } | |
| 149 | |
| 150 testClosureMirrors(mirrors) { | |
| 151 // TODO(ahe): Test optional parameters (named or not). | |
| 152 var closure = (x, y, z) { return x + y + z; }; | |
| 153 | |
| 154 var mirror = reflect(closure); | 20 var mirror = reflect(closure); |
| 155 expect(mirror is ClosureMirror, equals(true)); | 21 String rest = ' in s(_HashMap)'; // Might become Map instead. |
| 156 | 22 rest = ''; /// 01: ok |
| 157 var funcMirror = mirror.function; | 23 expect('Method(s(containsKey)$rest)', mirror.function); |
| 158 expect(funcMirror is MethodMirror, equals(true)); | 24 Expect.isFalse(mirror.apply([7]).reflectee); |
| 159 expect(funcMirror.parameters.length, equals(3)); | |
| 160 | |
| 161 expect(mirror.apply([7, 8, 9]).reflectee, equals(24)); | |
| 162 | |
| 163 var future = mirror.applyAsync([2, 4, 8]); | |
| 164 future.then(expectAsync1((resultMirror) { | |
| 165 expect(resultMirror.reflectee, equals(14)); | |
| 166 })); | |
| 167 } | |
| 168 | |
| 169 testInvokeConstructor(mirrors) { | |
| 170 var classMirror = reflectClass(Class); | |
| 171 | |
| 172 var instanceMirror = classMirror.newInstance(const Symbol(''),[]); | |
| 173 expect(instanceMirror.reflectee is Class, equals(true)); | |
| 174 expect(instanceMirror.reflectee.field, equals("default value")); | |
| 175 | |
| 176 instanceMirror = classMirror.newInstance(const Symbol('withInitialValue'), | |
| 177 [45]); | |
| 178 expect(instanceMirror.reflectee is Class, equals(true)); | |
| 179 expect(instanceMirror.reflectee.field, equals(45)); | |
| 180 | |
| 181 | |
| 182 instanceMirror = classMirror.newInstance(const Symbol('generative'), | |
| 183 [7]); | |
| 184 expect(instanceMirror.reflectee is Class, equals(true)); | |
| 185 expect(instanceMirror.reflectee.field, equals(7)); | |
| 186 | |
| 187 instanceMirror = classMirror.newInstance(const Symbol('redirecting'), | |
| 188 [8]); | |
| 189 expect(instanceMirror.reflectee is Class, equals(true)); | |
| 190 expect(instanceMirror.reflectee.field, equals(16)); | |
| 191 | |
| 192 instanceMirror = classMirror.newInstance(const Symbol('faktory'), | |
| 193 [9]); | |
| 194 expect(instanceMirror.reflectee is Class, equals(true)); | |
| 195 expect(instanceMirror.reflectee.field, equals(27)); | |
| 196 | |
| 197 instanceMirror = classMirror.newInstance(const Symbol('redirectingFactory'), | |
| 198 [10]); | |
| 199 if (!isDart2js) { | |
| 200 expect(instanceMirror.reflectee is Class, equals(true)); | |
| 201 expect(instanceMirror.reflectee.field, equals(30)); | |
| 202 } | |
| 203 | |
| 204 | |
| 205 var future = classMirror.newInstanceAsync(const Symbol(''), []); | |
| 206 future.then(expectAsync1((resultMirror) { | |
| 207 var instance = resultMirror.reflectee; | |
| 208 expect(instance is Class, equals(true)); | |
| 209 expect(instance.field, equals("default value")); | |
| 210 })); | |
| 211 | |
| 212 future = classMirror.newInstanceAsync(const Symbol('withInitialValue'), [45]); | |
| 213 future.then(expectAsync1((resultMirror) { | |
| 214 var instance = resultMirror.reflectee; | |
| 215 expect(instance is Class, equals(true)); | |
| 216 expect(instance.field, equals(45)); | |
| 217 })); | |
| 218 } | |
| 219 | |
| 220 testReflectClass(mirrors) { | |
| 221 var classMirror = reflectClass(Class); | |
| 222 expect(classMirror is ClassMirror, equals(true)); | |
| 223 var symbolClassMirror = reflectClass(Symbol); | |
| 224 var symbolMirror = symbolClassMirror.newInstance(const Symbol(''), | |
| 225 ['withInitialValue']); | |
| 226 if (isDart2js) return; | |
| 227 var objectMirror = classMirror.newInstance(symbolMirror.reflectee,[1234]); | |
| 228 expect(objectMirror.reflectee is Class, equals(true)); | |
| 229 expect(objectMirror.reflectee.field, equals(1234)); | |
| 230 } | |
| 231 | |
| 232 testNames(mirrors) { | |
| 233 var libMirror = mirrors.findLibrary(const Symbol("MirrorsTest")).single; | |
| 234 var classMirror = libMirror.classes[const Symbol('Class')]; | |
| 235 var typedefMirror = libMirror.members[const Symbol('Typedef')]; | |
| 236 var methodMirror = libMirror.functions[const Symbol('testNames')]; | |
| 237 var variableMirror = classMirror.variables[const Symbol('field')]; | |
| 238 | |
| 239 expect(libMirror.simpleName, equals(const Symbol('MirrorsTest'))); | |
| 240 expect(libMirror.qualifiedName, equals(const Symbol('MirrorsTest'))); | |
| 241 | |
| 242 expect(classMirror.simpleName, equals(const Symbol('Class'))); | |
| 243 expect(classMirror.qualifiedName, equals(const Symbol('MirrorsTest.Class'))); | |
| 244 | |
| 245 if (!isDart2js) { // TODO(ahe): Implement this in dart2js. | |
| 246 TypeVariableMirror typeVariable = classMirror.typeVariables.values.single; | |
| 247 expect(typeVariable.simpleName, equals(const Symbol('T'))); | |
| 248 expect(typeVariable.qualifiedName, | |
| 249 equals(const Symbol('MirrorsTest.Class.T'))); | |
| 250 | |
| 251 expect(typedefMirror.simpleName, equals(const Symbol('Typedef'))); | |
| 252 expect(typedefMirror.qualifiedName, | |
| 253 equals(const Symbol('MirrorsTest.Typedef'))); | |
| 254 | |
| 255 var typedefMirrorDeNovo = reflectClass(Typedef); | |
| 256 expect(typedefMirrorDeNovo.simpleName, equals(const Symbol('Typedef'))); | |
| 257 expect(typedefMirrorDeNovo.qualifiedName, | |
| 258 equals(const Symbol('MirrorsTest.Typedef'))); | |
| 259 } | |
| 260 | |
| 261 expect(methodMirror.simpleName, equals(const Symbol('testNames'))); | |
| 262 expect(methodMirror.qualifiedName, | |
| 263 equals(const Symbol('MirrorsTest.testNames'))); | |
| 264 | |
| 265 expect(variableMirror.simpleName, equals(const Symbol('field'))); | |
| 266 expect(variableMirror.qualifiedName, | |
| 267 equals(const Symbol('MirrorsTest.Class.field'))); | |
| 268 } | |
| 269 | |
| 270 testLibraryUri(var value, bool check(Uri)) { | |
| 271 var valueMirror = reflect(value); | |
| 272 ClassMirror valueClass = valueMirror.type; | |
| 273 LibraryMirror valueLibrary = valueClass.owner; | |
| 274 expect(check(valueLibrary.uri), isTrue); | |
| 275 } | 25 } |
| 276 | 26 |
| 277 main() { | 27 main() { |
| 278 var mirrors = currentMirrorSystem(); | 28 testIntercepted(); |
| 279 test("Test reflective method invocation", () { testInvoke(mirrors); }); | 29 testNonIntercepted(); |
| 280 test("Test instance field access", () { testInstanceFieldAccess(mirrors); }); | |
| 281 test('Test intercepted objects', () { testIntercepted(mirrors); }); | |
| 282 test("Test field access", () { testFieldAccess(mirrors); }); | |
| 283 test("Test closure mirrors", () { testClosureMirrors(mirrors); }); | |
| 284 test("Test invoke constructor", () { testInvokeConstructor(mirrors); }); | |
| 285 test("Test current library uri", () { | |
| 286 testLibraryUri(new Class(), | |
| 287 (Uri uri) => uri.path.endsWith('/mirrors_test.dart')); | |
| 288 }); | |
| 289 test("Test dart library uri", () { | |
| 290 testLibraryUri("test", (Uri uri) => uri == Uri.parse('dart:core')); | |
| 291 }); | |
| 292 test("Test simple and qualifiedName", () { testNames(mirrors); }); | |
| 293 test("Test reflect type", () { testReflectClass(mirrors); }); | |
| 294 } | 30 } |
| OLD | NEW |