Chromium Code Reviews| Index: tests/lib/mirrors/invoke_test.dart |
| =================================================================== |
| --- tests/lib/mirrors/invoke_test.dart (revision 0) |
| +++ tests/lib/mirrors/invoke_test.dart (revision 0) |
| @@ -0,0 +1,337 @@ |
| +// Copyright (c) 2013, 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. |
| + |
| +library test.invoke_test; |
| + |
| +import 'dart:mirrors'; |
| + |
| +import 'package:expect/expect.dart'; |
| +import '../../async_helper.dart'; |
| + |
| +class C { |
| + var field; |
| + C() : this.field = 'default'; |
| + C.named(this.field); |
| + |
| + get getter => 'get $field'; |
| + set setter(v) => field = 'set $v'; |
| + method(x, y, z) => '$x+$y+$z'; |
| + toString() => 'a C'; |
| + |
| + noSuchMethod(invocation) => 'DNU'; |
| + |
| + static var staticField = 'initial'; |
| + static get staticGetter => 'sget $staticField'; |
| + static set staticSetter(v) => staticField = 'sset $v'; |
| + static staticFunction(x, y) => "($x,$y)"; |
| +} |
| + |
| +var libraryField = 'a priori'; |
| +get libraryGetter => 'lget $libraryField'; |
| +set librarySetter(v) => libraryField = 'lset $v'; |
| +libraryFunction(x,y) => '$x$y'; |
| + |
| +shouldYieldValue(future) { |
| + asyncStart(); |
| + onValue(result) { |
| + asyncEnd(); |
| + return result; |
| + } |
| + onError(e) { |
| + Expect.fail("Value expected"); |
| + } |
| + return future.then(onValue, onError: onError); |
| +} |
| + |
| +shouldYieldError(future, errorPredicate, reason){ |
| + asyncStart(); |
| + onValue(result) { |
| + Expect.fail("Error expected ($reason)"); |
| + } |
| + onError(e) { |
| + asyncEnd(); |
| + if (!errorPredicate(e)) { |
| + Expect.fail("Unexpected error ($reason)"); |
| + } |
| + } |
| + return future.then(onValue, onError: onError); |
| +} |
| + |
| +// TODO(11957): Remove MirroredCompilationError. |
| +bool isInvokeError(e) { |
| + return e is MirroredCompilationError || e is NoSuchMethodError; |
| +} |
| + |
| +testSync() { |
| + var result; |
| + |
| + // InstanceMirror invoke |
| + C c = new C(); |
| + InstanceMirror im = reflect(c); |
| + result = im.invoke(const Symbol('method'), [2,4,8]); |
| + Expect.equals('2+4+8', result.reflectee); |
| + result = im.invoke(const Symbol('doesntExist'), [2,4,8]); |
| + Expect.equals('DNU', result.reflectee); |
| + result = im.invoke(const Symbol('method'), [2,4]); // Wrong arity. |
| + Expect.equals('DNU', result.reflectee); |
| + |
| + // InstanceMirror invokeGetter |
| + result = im.getField(const Symbol('getter')); |
| + Expect.equals('get default', result.reflectee); |
| + result = im.getField(const Symbol('field')); |
| + Expect.equals('default', result.reflectee); |
| + result = im.getField(const Symbol('doesntExist')); |
| + Expect.equals('DNU', result.reflectee); |
| + |
| + // InstanceMirror invokeSetter |
| + im.setField(const Symbol('setter'), 'foo'); |
| + Expect.equals('set foo', c.field); |
|
ahe
2013/07/24 09:43:35
Could you also test that getField still return the
|
| + im.setField(const Symbol('field'), 'bar'); |
| + Expect.equals('bar', c.field); |
| + // The following invocation we merely expect not to throw an expection |
| + // because noSuchMethod is implemented. There is no side-effect to test for. |
| + im.setField(const Symbol('doesntExist'), 'bar'); |
|
ahe
2013/07/24 09:43:35
You could test that it returns 'bar'.
rmacnak
2013/07/24 17:03:19
Pending https://codereview.chromium.org/20066004/
|
| + |
| + // ClassMirror invoke |
| + ClassMirror cm = reflectClass(C); |
| + result = cm.invoke(const Symbol('staticFunction'),[3,4]); |
| + Expect.equals('(3,4)', result.reflectee); |
| + Expect.throws(() => cm.invoke(const Symbol('doesntExist'),[3,4]), |
| + isInvokeError, |
| + 'Not defined'); |
| + Expect.throws(() => cm.invoke(const Symbol('staticFunction'),[3]), |
| + isInvokeError, |
| + 'Wrong arity'); |
| + |
| + // ClassMirror invokeGetter |
| + result = cm.getField(const Symbol('staticGetter')); |
| + Expect.equals('sget initial', result.reflectee); |
| + result = cm.getField(const Symbol('staticField')); |
| + Expect.equals('initial', result.reflectee); |
| + Expect.throws(() => cm.getField(const Symbol('doesntExist')), |
| + isInvokeError, |
| + 'Not defined'); |
| + |
| + // ClassMirror invokeSetter |
| + cm.setField(const Symbol('staticSetter'), 'sfoo'); |
| + Expect.equals('sset sfoo', C.staticField); |
|
ahe
2013/07/24 09:43:35
Again, it would be nice if you also test that getF
|
| + cm.setField(const Symbol('staticField'), 'sbar'); |
| + Expect.equals('sbar', C.staticField); |
| + Expect.throws(() => cm.setField(const Symbol('doesntExist'), 'sbar'), |
| + isInvokeError, |
| + 'Not defined'); |
| + |
| + // ClassMirror invokeConstructor |
| + result = cm.newInstance(const Symbol(''), []); |
| + Expect.isTrue(result.reflectee is C); |
| + Expect.equals('default', result.reflectee.field); |
| + result = cm.newInstance(const Symbol('named'), ['my value']); |
| + Expect.isTrue(result.reflectee is C); |
| + Expect.equals('my value', result.reflectee.field); |
| + Expect.throws(() => cm.newInstance(const Symbol('doesntExist'), ['my value']), |
| + isInvokeError, |
| + 'Not defined'); |
| + Expect.throws(() => cm.newInstance(const Symbol('named'), []), |
| + isInvokeError, |
| + 'Wrong arity'); |
| + |
| + // LibraryMirror invoke |
| + LibraryMirror lm = cm.owner; |
| + result = lm.invoke(const Symbol('libraryFunction'),[':',')']); |
| + Expect.equals(':)', result.reflectee); |
|
ahe
2013/07/24 09:43:35
:)
rmacnak
2013/07/24 17:03:19
:D
|
| + Expect.throws(() => lm.invoke(const Symbol('doesntExist'), [':',')']), |
| + isInvokeError, |
| + 'Not defined'); |
| + Expect.throws(() => lm.invoke(const Symbol('libraryFunction'), [':']), |
| + isInvokeError, |
| + 'Wrong arity'); |
| + |
| + // LibraryMirror invokeGetter |
| + result = lm.getField(const Symbol('libraryGetter')); |
| + Expect.equals('lget a priori', result.reflectee); |
| + result = lm.getField(const Symbol('libraryField')); |
| + Expect.equals('a priori', result.reflectee); |
| + Expect.throws(() => lm.getField(const Symbol('doesntExist')), |
| + isInvokeError, |
| + 'Not defined'); |
| + |
| + // LibraryMirror invokeSetter |
| + lm.setField(const Symbol('librarySetter'), 'lfoo'); |
| + Expect.equals('lset lfoo', libraryField); |
|
ahe
2013/07/24 09:43:35
Again, it would be nice if you test getField still
|
| + lm.setField(const Symbol('libraryField'), 'lbar'); |
| + Expect.equals('lbar', libraryField); |
| + Expect.throws(() => lm.setField(const Symbol('doesntExist'), 'lbar'), |
| + isInvokeError, |
| + 'Not defined'); |
| +} |
| + |
| +testAsync() { |
|
ahe
2013/07/24 09:43:35
I think you need to chain most of the futures in t
rmacnak
2013/07/24 17:03:19
Something like
shouldYieldValue(m.somethingAync).
ahe
2013/07/25 09:09:37
Let's ask Florian for help.
|
| + var future; |
| + |
| + // InstanceMirror invoke |
| + C c = new C(); |
| + InstanceMirror im = reflect(c); |
| + future = im.invokeAsync(const Symbol('method'), [2,4,8]); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('2+4+8', result.reflectee); |
| + }); |
|
ahe
2013/07/25 12:03:33
Florian points out that this would be safer:
s
|
| + future = im.invokeAsync(const Symbol('method'), [im,im,im]); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('a C+a C+a C', result.reflectee); |
| + }); |
| + future = im.invokeAsync(const Symbol('doesntExist'), [2,4,8]); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('DNU', result.reflectee); |
| + }); |
| + future = im.invokeAsync(const Symbol('method'), [2, 4]); // Wrong arity. |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('DNU', result.reflectee); |
| + }); |
| + |
| + // InstanceMirror invokeGetter |
| + future = im.getFieldAsync(const Symbol('getter')); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('get default', result.reflectee); |
| + }); |
| + future = im.getFieldAsync(const Symbol('field')); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('default', result.reflectee); |
| + }); |
| + future = im.getFieldAsync(const Symbol('doesntExist')); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('DNU', result.reflectee); |
| + }); |
| + |
| + // InstanceMirror invokeSetter |
| + future = im.setFieldAsync(const Symbol('setter'), 'foo'); |
| + shouldYieldValue(future).then((result) { |
|
ahe
2013/07/24 09:43:35
Check result.
floitsch
2013/07/25 12:42:58
This can be written as:
shouldYieldValue(
im.set
|
| + Expect.equals('set foo', c.field); |
| + var future2 = im.setFieldAsync(const Symbol('field'), 'bar'); |
| + shouldYieldValue(future2).then((result) { |
|
ahe
2013/07/24 09:43:35
Check result.
|
| + Expect.equals('bar', c.field); |
| + var future3 = im.setFieldAsync(const Symbol('field'), im); |
| + shouldYieldValue(future3).then((result) { |
|
ahe
2013/07/24 09:43:35
Check result.
|
| + Expect.equals(c, c.field); |
| + }); |
| + }); |
| + }); |
| + future = im.setFieldAsync(const Symbol('doesntExist'), 'bar'); |
| + shouldYieldValue(future); |
|
ahe
2013/07/24 09:43:35
I think you should test the returned value.
|
| + |
| + |
| + // ClassMirror invoke |
| + ClassMirror cm = reflectClass(C); |
| + future = cm.invokeAsync(const Symbol('staticFunction'),[3,4]); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('(3,4)', result.reflectee); |
| + }); |
| + future = cm.invokeAsync(const Symbol('staticFunction'),[im,im]); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('(a C,a C)', result.reflectee); |
| + }); |
| + future = cm.invokeAsync(const Symbol('doesntExist'),[im,im]); |
| + shouldYieldError(future, isInvokeError, 'Not defined'); |
| + future = cm.invokeAsync(const Symbol('staticFunction'),[3]); |
| + shouldYieldError(future, isInvokeError, 'Wrong arity'); |
| + |
| + // ClassMirror invokeGetter |
| + C.staticField = 'initial'; // Reset from synchronous test. |
| + future = cm.getFieldAsync(const Symbol('staticGetter')); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('sget initial', result.reflectee); |
| + }); |
| + future = cm.getFieldAsync(const Symbol('staticField')); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('initial', result.reflectee); |
| + }); |
| + future = cm.getFieldAsync(const Symbol('doesntExist')); |
| + shouldYieldError(future, isInvokeError, 'Not defined'); |
| + |
| + // ClassMirror invokeSetter |
| + future = cm.setFieldAsync(const Symbol('staticSetter'), 'sfoo'); |
| + shouldYieldValue(future).then((result) { |
|
floitsch
2013/07/25 12:42:58
ditto (use implicit chaining).
|
| + Expect.equals('sset sfoo', C.staticField); |
| + var future2 = cm.setFieldAsync(const Symbol('staticField'), 'sbar'); |
| + shouldYieldValue(future2).then((result) { |
|
ahe
2013/07/24 09:43:35
Check result.
|
| + Expect.equals('sbar', C.staticField); |
| + var future3 = cm.setFieldAsync(const Symbol('staticField'), im);; |
| + shouldYieldValue(future3).then((result) { |
|
ahe
2013/07/24 09:43:35
Check result.
|
| + Expect.equals(c, C.staticField); |
| + }); |
| + }); |
| + }); |
| + future = cm.setFieldAsync(const Symbol('doesntExist'), 'sbar'); |
| + shouldYieldError(future, isInvokeError, 'Not defined'); |
| + |
| + // ClassMirror invokeConstructor |
| + future = cm.newInstanceAsync(const Symbol(''), []); |
| + shouldYieldValue(future).then((result) { |
| + Expect.isTrue(result.reflectee is C); |
| + Expect.equals('default', result.reflectee.field); |
| + }); |
| + future = cm.newInstanceAsync(const Symbol('named'), ['my value']); |
| + shouldYieldValue(future).then((result) { |
| + Expect.isTrue(result.reflectee is C); |
| + Expect.equals('my value', result.reflectee.field); |
| + }); |
| + future = cm.newInstanceAsync(const Symbol('named'), [im]); |
| + shouldYieldValue(future).then((result) { |
| + Expect.isTrue(result.reflectee is C); |
| + Expect.equals(c, result.reflectee.field); |
| + }); |
| + future = cm.newInstanceAsync(const Symbol('doesntExist'), ['my value']); |
| + shouldYieldError(future, isInvokeError, 'Not defined'); |
| + future = cm.newInstanceAsync(const Symbol('named'), []); |
| + shouldYieldError(future, isInvokeError, 'Wrong arity'); |
| + |
| + |
| + // LibraryMirror invoke |
| + LibraryMirror lm = cm.owner; |
| + future = lm.invokeAsync(const Symbol('libraryFunction'),[':',')']); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals(':)', result.reflectee); |
| + }); |
| + future = lm.invokeAsync(const Symbol('libraryFunction'),[im,im]); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('a Ca C', result.reflectee); |
| + }); |
| + future = lm.invokeAsync(const Symbol('doesntExist'),[im,im]); |
| + shouldYieldError(future, isInvokeError, 'Not defined'); |
| + future = lm.invokeAsync(const Symbol('libraryFunction'),[':']); // Wrong arity. |
|
ahe
2013/07/24 09:43:35
Long line.
|
| + shouldYieldError(future, isInvokeError, 'Wrong arity'); |
| + |
| + // LibraryMirror invokeGetter |
| + libraryField = 'a priori'; // Reset from synchronous test. |
| + future = lm.getFieldAsync(const Symbol('libraryGetter')); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('lget a priori', result.reflectee); |
| + }); |
| + future = lm.getFieldAsync(const Symbol('libraryField')); |
| + shouldYieldValue(future).then((result) { |
| + Expect.equals('a priori', result.reflectee); |
| + }); |
| + future = lm.getFieldAsync(const Symbol('doesntExist')); |
| + shouldYieldError(future, isInvokeError, 'Not defined'); |
| + |
| + // LibraryMirror invokeSetter |
| + future = lm.setFieldAsync(const Symbol('librarySetter'), 'lfoo'); |
|
floitsch
2013/07/25 12:42:58
same here (implicit chaining).
|
| + shouldYieldValue(future).then((result) { |
|
ahe
2013/07/24 09:43:35
Check result.
|
| + Expect.equals('lset lfoo', libraryField); |
| + var future2 = lm.setFieldAsync(const Symbol('libraryField'), 'lbar'); |
| + shouldYieldValue(future2).then((result) { |
|
ahe
2013/07/24 09:43:35
Check result.
|
| + Expect.equals('lbar', libraryField); |
| + var future3 = lm.setFieldAsync(const Symbol('libraryField'), im); |
| + shouldYieldValue(future3).then((result) { |
|
ahe
2013/07/24 09:43:35
Check result.
|
| + Expect.equals(c, libraryField); |
| + }); |
| + }); |
| + }); |
| + future = lm.setFieldAsync(const Symbol('doesntExist'), 'lbar'); |
| + shouldYieldError(future, isInvokeError, 'Not defined'); |
| +} |
| + |
| +main() { |
| + testSync(); |
| + testAsync(); |
| +} |