| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| // |
| // Dart test program for checking implemention of MirrorSystem when |
| // inspecting the current isolate. |
| // |
| // VMOptions=--enable_type_checks |
| |
| library isolate_mirror_local_test; |
| |
| import "package:expect/expect.dart"; |
| import 'dart:async'; |
| import 'dart:isolate'; |
| import 'dart:mirrors'; |
| |
| ReceivePort exit_port; |
| Set expectedTests; |
| |
| void testDone(String test) { |
| if (!expectedTests.contains(test)) { |
| throw "Unexpected test name '$test'"; |
| } |
| expectedTests.remove(test); |
| if (expectedTests.isEmpty) { |
| // All tests are done. |
| exit_port.close(); |
| } |
| } |
| |
| int global_var = 0; |
| final int final_global_var = 0; |
| |
| // Top-level getter and setter. |
| int get myVar { return 5; } |
| void set myVar(x) {} |
| |
| // This function will be invoked reflectively. |
| int function(int x) { |
| global_var = x; |
| return x + 1; |
| } |
| |
| typedef void FuncType(String a); |
| |
| FuncType myFunc = null; |
| |
| _stringCompare(String a, String b) => a.compareTo(b); |
| sort(list) => list.sort(_stringCompare); |
| |
| String buildMethodString(MethodMirror func) { |
| var result = '${MirrorSystem.getName(func.simpleName)} ' |
| 'return(${MirrorSystem.getName(func.returnType.simpleName)})'; |
| if (func.isPrivate) { |
| result = '$result private'; |
| } |
| if (func.isTopLevel) { |
| result = '$result toplevel'; |
| } |
| if (func.isStatic) { |
| result = '$result static'; |
| } |
| if (func.isAbstract) { |
| result = '$result abstract'; |
| } |
| if (func.isRegularMethod) { |
| result = '$result method'; |
| } |
| if (func.isGetter) { |
| result = '$result getter'; |
| } |
| if (func.isSetter) { |
| result = '$result setter'; |
| } |
| if (func.isConstructor) { |
| result = '$result constructor'; |
| } |
| if (func.isConstConstructor) { |
| result = '$result const'; |
| } |
| if (func.isGenerativeConstructor) { |
| result = '$result generative'; |
| } |
| if (func.isRedirectingConstructor) { |
| result = '$result redirecting'; |
| } |
| if (func.isFactoryConstructor) { |
| result = '$result factory'; |
| } |
| return result; |
| } |
| |
| String buildVariableString(VariableMirror variable) { |
| var result = '${MirrorSystem.getName(variable.simpleName)} ' |
| 'type(${MirrorSystem.getName(variable.type.simpleName)})'; |
| if (variable.isPrivate) { |
| result = '$result private'; |
| } |
| if (variable.isTopLevel) { |
| result = '$result toplevel'; |
| } |
| if (variable.isStatic) { |
| result = '$result static'; |
| } |
| if (variable.isFinal) { |
| result = '$result final'; |
| } |
| return result; |
| } |
| |
| void testRootLibraryMirror(LibraryMirror lib_mirror) { |
| Expect.equals(const Symbol('isolate_mirror_local_test'), |
| lib_mirror.simpleName); |
| Expect.equals(const Symbol('isolate_mirror_local_test'), |
| lib_mirror.qualifiedName); |
| Expect.equals(null, lib_mirror.owner); |
| Expect.isFalse(lib_mirror.isPrivate); |
| Expect.isTrue(lib_mirror.uri.path.contains('isolate_mirror_local_test.dart')); |
| Expect.equals("LibraryMirror on 'isolate_mirror_local_test'", |
| lib_mirror.toString()); |
| |
| // Test library invocation by calling function(123). |
| Expect.equals(0, global_var); |
| lib_mirror.invokeAsync(const Symbol('function'), [123]).then( |
| (InstanceMirror retval) { |
| Expect.equals(123, global_var); |
| Expect.equals(const Symbol('int'), retval.type.simpleName); |
| Expect.isTrue(retval.hasReflectee); |
| Expect.equals(124, retval.reflectee); |
| testDone('testRootLibraryMirror'); |
| }); |
| |
| // Check that the members map is complete. |
| List keys = lib_mirror.members.keys.map(MirrorSystem.getName).toList(); |
| sort(keys); |
| Expect.equals('[' |
| 'FuncType, ' |
| 'GenericClass, ' |
| 'MyClass, ' |
| 'MyException, ' |
| 'MyInterface, ' |
| 'MySuperClass, ' |
| '_stringCompare, ' |
| 'buildMethodString, ' |
| 'buildVariableString, ' |
| 'exit_port, ' |
| 'expectedTests, ' |
| 'final_global_var, ' |
| 'function, ' |
| 'global_var, ' |
| 'main, ' |
| 'methodWithError, ' |
| 'methodWithException, ' |
| 'myFunc, ' |
| 'myVar, ' |
| 'myVar=, ' |
| 'sort, ' |
| 'testBoolInstanceMirror, ' |
| 'testCustomInstanceMirror, ' |
| 'testDone, ' |
| 'testIntegerInstanceMirror, ' |
| 'testLibrariesMap, ' |
| 'testMirrorErrors, ' |
| 'testMirrorSystem, ' |
| 'testNullInstanceMirror, ' |
| 'testRootLibraryMirror, ' |
| 'testStringInstanceMirror]', |
| '$keys'); |
| |
| // Check that the classes map is complete. |
| keys = lib_mirror.classes.keys.map(MirrorSystem.getName).toList(); |
| sort(keys); |
| Expect.equals('[' |
| 'FuncType, ' |
| 'GenericClass, ' |
| 'MyClass, ' |
| 'MyException, ' |
| 'MyInterface, ' |
| 'MySuperClass]', |
| '$keys'); |
| |
| // Check that the functions map is complete. |
| keys = lib_mirror.functions.keys.map(MirrorSystem.getName).toList(); |
| sort(keys); |
| Expect.equals('[' |
| '_stringCompare, ' |
| 'buildMethodString, ' |
| 'buildVariableString, ' |
| 'function, ' |
| 'main, ' |
| 'methodWithError, ' |
| 'methodWithException, ' |
| 'myVar, ' |
| 'myVar=, ' |
| 'sort, ' |
| 'testBoolInstanceMirror, ' |
| 'testCustomInstanceMirror, ' |
| 'testDone, ' |
| 'testIntegerInstanceMirror, ' |
| 'testLibrariesMap, ' |
| 'testMirrorErrors, ' |
| 'testMirrorSystem, ' |
| 'testNullInstanceMirror, ' |
| 'testRootLibraryMirror, ' |
| 'testStringInstanceMirror]', |
| '$keys'); |
| |
| // Check that the getters map is complete. |
| keys = lib_mirror.getters.keys.map(MirrorSystem.getName).toList(); |
| sort(keys); |
| Expect.equals('[myVar]', '$keys'); |
| |
| // Check that the setters map is complete. |
| keys = lib_mirror.setters.keys.map(MirrorSystem.getName).toList(); |
| sort(keys); |
| Expect.equals('[myVar=]', '$keys'); |
| |
| // Check that the variables map is complete. |
| keys = lib_mirror.variables.keys.map(MirrorSystem.getName).toList(); |
| sort(keys); |
| Expect.equals('[' |
| 'exit_port, ' |
| 'expectedTests, ' |
| 'final_global_var, ' |
| 'global_var, ' |
| 'myFunc]', |
| '$keys'); |
| |
| ClassMirror cls_mirror = lib_mirror.members[const Symbol('MyClass')]; |
| ClassMirror generic_cls_mirror = |
| lib_mirror.members[const Symbol('GenericClass')]; |
| |
| // Test function mirrors. |
| MethodMirror func = lib_mirror.members[const Symbol('function')]; |
| Expect.isTrue(func is MethodMirror); |
| Expect.equals('function return(int) toplevel static method', |
| buildMethodString(func)); |
| |
| func = lib_mirror.members[const Symbol('myVar')]; |
| Expect.isTrue(func is MethodMirror); |
| Expect.equals('myVar return(int) toplevel static getter', |
| buildMethodString(func)); |
| |
| func = lib_mirror.members[const Symbol('myVar=')]; |
| Expect.isTrue(func is MethodMirror); |
| Expect.equals('myVar= return(void) toplevel static setter', |
| buildMethodString(func)); |
| |
| func = cls_mirror.members[const Symbol('method')]; |
| Expect.isTrue(func is MethodMirror); |
| Expect.equals('method return(int) method', buildMethodString(func)); |
| |
| func = cls_mirror.constructors[const Symbol('MyClass')]; |
| Expect.isTrue(func is MethodMirror); |
| Expect.equals('MyClass return(MyClass) constructor', buildMethodString(func)); |
| |
| func = cls_mirror.constructors[const Symbol('MyClass.named')]; |
| Expect.isTrue(func is MethodMirror); |
| Expect.equals('MyClass.named return(MyClass) constructor', |
| buildMethodString(func)); |
| |
| func = generic_cls_mirror.members[const Symbol('method')]; |
| Expect.isTrue(func is MethodMirror); |
| Expect.equals('method return(T) method', buildMethodString(func)); |
| |
| // Test variable mirrors. |
| VariableMirror variable = lib_mirror.members[const Symbol('global_var')]; |
| Expect.isTrue(variable is VariableMirror); |
| Expect.equals('global_var type(int) toplevel static', |
| buildVariableString(variable)); |
| |
| variable = lib_mirror.members[const Symbol('final_global_var')]; |
| Expect.isTrue(variable is VariableMirror); |
| Expect.equals('final_global_var type(int) toplevel static final', |
| buildVariableString(variable)); |
| |
| variable = cls_mirror.members[const Symbol('value')]; |
| Expect.isTrue(variable is VariableMirror); |
| Expect.equals('value type(dynamic) final', buildVariableString(variable)); |
| |
| // Test type variable mirrors. |
| var type_var = generic_cls_mirror.members[const Symbol('method')].returnType; |
| Expect.isTrue(type_var is TypeVariableMirror); |
| Expect.equals(const Symbol('GenericClass'), type_var.owner.simpleName); |
| Expect.equals(const Symbol('Object'), type_var.upperBound.simpleName); |
| |
| // Test typedef mirrors. |
| var typedef_mirror = lib_mirror.members[const Symbol('myFunc')].type; |
| Expect.isTrue(typedef_mirror is TypedefMirror); |
| Expect.equals(const Symbol('isolate_mirror_local_test'), |
| typedef_mirror.owner.simpleName); |
| |
| // Test function type mirrors. |
| var func_cls_mirror = typedef_mirror.referent; |
| Expect.isTrue(func_cls_mirror is FunctionTypeMirror); |
| // Expect.equals('void (dart.core.String)', func_cls_mirror.simpleName); |
| Expect.equals(const Symbol('void'), func_cls_mirror.returnType.simpleName); |
| } |
| |
| void testLibrariesMap(Map libraries) { |
| // Just look for a couple of well-known libs. |
| LibraryMirror core_lib = libraries[Uri.parse('dart:core')]; |
| Expect.isTrue(core_lib is LibraryMirror); |
| |
| LibraryMirror mirror_lib = libraries[Uri.parse('dart:mirrors')]; |
| Expect.isTrue(mirror_lib is LibraryMirror); |
| |
| // Lookup an interface from a library and make sure it is sane. |
| ClassMirror list_intf = core_lib.members[const Symbol('List')]; |
| Expect.isTrue(list_intf is ClassMirror); |
| Expect.equals(const Symbol('List'), list_intf.simpleName); |
| Expect.equals(const Symbol('dart.core.List'), list_intf.qualifiedName); |
| Expect.isFalse(list_intf.isPrivate); |
| Expect.equals(const Symbol('Object'), list_intf.superclass.simpleName); |
| Expect.equals(const Symbol('dart.core'), list_intf.owner.simpleName); |
| Expect.isTrue(list_intf.isClass); |
| Expect.equals(const Symbol('Iterable'), |
| list_intf.superinterfaces[0].simpleName); |
| Expect.equals("ClassMirror on 'List'", list_intf.toString()); |
| |
| // Lookup a class from a library and make sure it is sane. |
| ClassMirror oom_cls = core_lib.members[const Symbol('OutOfMemoryError')]; |
| Expect.isTrue(oom_cls is ClassMirror); |
| Expect.equals(const Symbol('OutOfMemoryError'), oom_cls.simpleName); |
| Expect.equals(const Symbol('dart.core.OutOfMemoryError'), |
| oom_cls.qualifiedName); |
| Expect.isFalse(oom_cls.isPrivate); |
| Expect.equals(const Symbol('Object'), oom_cls.superclass.simpleName); |
| Expect.isTrue(oom_cls.defaultFactory == null); |
| Expect.equals(const Symbol('dart.core'), oom_cls.owner.simpleName); |
| Expect.isTrue(oom_cls.isClass); |
| Expect.equals(const Symbol('Error'), oom_cls.superinterfaces[0].simpleName); |
| Expect.equals("ClassMirror on 'OutOfMemoryError'", |
| oom_cls.toString()); |
| testDone('testLibrariesMap'); |
| } |
| |
| void testMirrorSystem(MirrorSystem mirrors) { |
| Expect.isTrue(mirrors.isolate.debugName.contains('main')); |
| testRootLibraryMirror(mirrors.isolate.rootLibrary); |
| testLibrariesMap(mirrors.libraries); |
| Expect.equals(const Symbol('void'), mirrors.voidType.simpleName); |
| Expect.equals(const Symbol('dynamic'), mirrors.dynamicType.simpleName); |
| Expect.isTrue(mirrors.voidType is TypeMirror); |
| Expect.isTrue(mirrors.dynamicType is TypeMirror); |
| Expect.isFalse(mirrors.voidType is ClassMirror); |
| Expect.isFalse(mirrors.dynamicType is ClassMirror); |
| testDone('testMirrorSystem'); |
| } |
| |
| void testIntegerInstanceMirror(InstanceMirror mirror) { |
| Expect.equals(const Symbol('int'), mirror.type.simpleName); |
| Expect.isTrue(mirror.hasReflectee); |
| Expect.equals(1001, mirror.reflectee); |
| Expect.equals("InstanceMirror on 1001", mirror.toString()); |
| |
| // Invoke (mirror + mirror). |
| mirror.invokeAsync(const Symbol('+'), [ mirror ]).then( |
| (InstanceMirror retval) { |
| Expect.equals(const Symbol('int'), retval.type.simpleName); |
| Expect.isTrue(retval.hasReflectee); |
| Expect.equals(2002, retval.reflectee); |
| testDone('testIntegerInstanceMirror'); |
| }); |
| } |
| |
| void testStringInstanceMirror(InstanceMirror mirror) { |
| Expect.equals(const Symbol('String'), mirror.type.simpleName); |
| Expect.isTrue(mirror.hasReflectee); |
| Expect.equals('This\nis\na\nString', mirror.reflectee); |
| Expect.equals('InstanceMirror on "This\\nis\\na\\nString"', |
| mirror.toString()); |
| |
| // Invoke mirror[0]. |
| mirror.invokeAsync(const Symbol('[]'), [ 0 ]).then( |
| (InstanceMirror retval) { |
| Expect.equals(const Symbol('String'), retval.type.simpleName); |
| Expect.isTrue(retval.hasReflectee); |
| Expect.equals('T', retval.reflectee); |
| testDone('testStringInstanceMirror'); |
| }); |
| } |
| |
| void testBoolInstanceMirror(InstanceMirror mirror) { |
| Expect.equals(const Symbol('bool'), mirror.type.simpleName); |
| Expect.isTrue(mirror.hasReflectee); |
| Expect.equals(true, mirror.reflectee); |
| Expect.equals("InstanceMirror on true", mirror.toString()); |
| testDone('testBoolInstanceMirror'); |
| } |
| |
| void testNullInstanceMirror(InstanceMirror mirror) { |
| Expect.equals(const Symbol('Null'), mirror.type.simpleName); |
| Expect.isTrue(mirror.hasReflectee); |
| Expect.equals(null, mirror.reflectee); |
| Expect.equals("InstanceMirror on null", mirror.toString()); |
| testDone('testNullInstanceMirror'); |
| } |
| |
| class MySuperClass { |
| } |
| |
| class MyInterface { |
| } |
| |
| @notDefined |
| class MyClass extends MySuperClass implements MyInterface { |
| MyClass(this.value) {} |
| MyClass.named() {} |
| |
| final value; |
| |
| int method(int arg) { |
| return arg + value; |
| } |
| } |
| |
| class GenericClass<T> { |
| T method(int arg) { |
| return null; |
| } |
| } |
| |
| void testCustomInstanceMirror(InstanceMirror mirror) { |
| Expect.isTrue(mirror.hasReflectee); |
| bool saw_exception = false; |
| try { |
| mirror.reflectee; |
| } on MirrorException catch (me) { |
| saw_exception = true; |
| } |
| Expect.isFalse(saw_exception); |
| Expect.equals("InstanceMirror on Instance of 'MyClass'", |
| mirror.toString()); |
| |
| ClassMirror cls = mirror.type; |
| Expect.isTrue(cls is ClassMirror); |
| Expect.equals(const Symbol('MyClass'), cls.simpleName); |
| Expect.equals(const Symbol('MySuperClass'), cls.superclass.simpleName); |
| Expect.isTrue(cls.defaultFactory == null); |
| Expect.equals(const Symbol('isolate_mirror_local_test'), |
| cls.owner.simpleName); |
| Expect.isTrue(cls.isClass); |
| Expect.equals(const Symbol('MyInterface'), cls.superinterfaces[0].simpleName); |
| Expect.throws(() => cls.metadata, |
| (e) => e is MirroredCompilationError, |
| 'Bad metadata'); |
| Expect.equals("ClassMirror on 'MyClass'", cls.toString()); |
| |
| // Invoke mirror.method(1000). |
| mirror.invokeAsync(const Symbol('method'), [ 1000 ]).then( |
| (InstanceMirror retval) { |
| Expect.equals(const Symbol('int'), retval.type.simpleName); |
| Expect.isTrue(retval.hasReflectee); |
| Expect.equals(1017, retval.reflectee); |
| testDone('testCustomInstanceMirror'); |
| }); |
| |
| } |
| |
| class MyException implements Exception { |
| MyException(this._message); |
| final String _message; |
| String toString() { return 'MyException: $_message'; } |
| } |
| |
| void methodWithException() { |
| throw new MyException("from methodWithException"); |
| } |
| |
| void methodWithError() { |
| // We get a parse error when we try to run this function. |
| +++; |
| } |
| |
| void testMirrorErrors(MirrorSystem mirrors) { |
| LibraryMirror lib_mirror = mirrors.isolate.rootLibrary; |
| |
| lib_mirror.invokeAsync(const Symbol('methodWithException'), []) |
| .then((InstanceMirror retval) { |
| // Should not reach here. |
| Expect.isTrue(false); |
| }) |
| .catchError((error) { |
| Expect.isTrue(error is MyException); |
| Expect.equals('MyException: from methodWithException', |
| error.toString()); |
| testDone('testMirrorErrors1'); |
| }); |
| |
| lib_mirror.invokeAsync(const Symbol('methodWithError'), []) |
| .then((InstanceMirror retval) { |
| // Should not reach here. |
| Expect.isTrue(false); |
| }) |
| .catchError((error) { |
| Expect.isTrue(error is MirroredCompilationError); |
| Expect.isTrue(error.message.contains('unexpected token')); |
| testDone('testMirrorErrors2'); |
| }); |
| |
| // TODO(turnidge): When we call a method that doesn't exist, we |
| // should probably call noSuchMethod(). I'm adding this test to |
| // document the current behavior in the meantime. |
| lib_mirror.invokeAsync(const Symbol('methodNotFound'), []) |
| .then((InstanceMirror retval) { |
| // Should not reach here. |
| Expect.isTrue(false); |
| }) |
| .catchError((error) { |
| Expect.isTrue(error is NoSuchMethodError); |
| Expect.isTrue(error.toString().contains( |
| "No top-level method 'methodNotFound'")); |
| testDone('testMirrorErrors3'); |
| }); |
| } |
| |
| void main() { |
| // When all of the expected tests complete, the exit_port is closed, |
| // allowing the program to terminate. |
| exit_port = new ReceivePort(); |
| expectedTests = new Set<String>.from(['testRootLibraryMirror', |
| 'testLibrariesMap', |
| 'testMirrorSystem', |
| 'testIntegerInstanceMirror', |
| 'testStringInstanceMirror', |
| 'testBoolInstanceMirror', |
| 'testNullInstanceMirror', |
| 'testCustomInstanceMirror', |
| 'testMirrorErrors1', |
| 'testMirrorErrors2', |
| 'testMirrorErrors3']); |
| |
| // Test that an isolate can reflect on itself. |
| mirrorSystemOf(exit_port.toSendPort()).then(testMirrorSystem); |
| |
| testIntegerInstanceMirror(reflect(1001)); |
| testStringInstanceMirror(reflect('This\nis\na\nString')); |
| testBoolInstanceMirror(reflect(true)); |
| testNullInstanceMirror(reflect(null)); |
| testCustomInstanceMirror(reflect(new MyClass(17))); |
| testMirrorErrors(currentMirrorSystem()); |
| } |