Files
sdk/tests/language/invocation_mirror_test.dart
T
Jacob Richman 2dcd56ef43 Format all tests.
There are far too many files here to review everyone carefully.
Spot checking most of the diffs look good as test code is generally written
with less care than application code so lots of ugly formatting get through.
If people notice files where the automated formatting bothers them feel free
to comment indicating file names and I'll move spaces within comments to make
the formatting cleaner and use comments to force block formatting as I have
done for other case where formatting looked bad.

BUG=
R=efortuna@google.com

Review-Url: https://codereview.chromium.org/2771453003 .
2017-04-17 14:53:02 -07:00

327 lines
11 KiB
Dart

// 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.
import "package:expect/expect.dart";
// Invocation and noSuchMethod testing.
Map<Symbol, dynamic> listToNamedArguments(list) {
var iterator = list.iterator;
var result = new Map<Symbol, dynamic>();
while (iterator.moveNext()) {
Symbol key = iterator.current;
Expect.isTrue(iterator.moveNext());
result[key] = iterator.current;
}
return result;
}
/** Class with noSuchMethod that returns the mirror */
class N {
// Storage for the last argument to noSuchMethod.
// Needed for setters, which don't evaluate to the return value.
var last;
noSuchMethod(Invocation m) => last = m;
flif(int x) {
Expect.fail("never get here");
}
flaf([int x]) {
Expect.fail("never get here");
}
flof({int y}) {
Expect.fail("never get here");
}
get wut => this;
final int plif = 99;
int get plaf {
Expect.fail("never get here");
return 0;
}
}
/** As [N] but also implements 'call', so we can call it with wrong arguments.*/
class C extends N {
call(int x) {
Expect.fail("never get here");
}
}
/**
* Checks the data of an Invocation.
*
* Call without optionals for getters, with only positional for setters,
* and with both optionals for everything else.
*/
testInvocationMirror(Invocation im, Symbol name,
[List positional, List named]) {
Expect.isTrue(im is Invocation, "is Invocation");
Expect.equals(name, im.memberName, "name");
if (named == null) {
Expect.isTrue(im.isAccessor, "$name:isAccessor");
Expect.isFalse(im.isMethod, "$name:isMethod");
if (positional == null) {
Expect.isTrue(im.isGetter, "$name:isGetter");
Expect.isFalse(im.isSetter, "$name:isSetter");
Expect.equals(0, im.positionalArguments.length, "$name:#positional");
Expect.equals(0, im.namedArguments.length, "$name:#named");
return;
}
Expect.isTrue(im.isSetter, "$name:isSetter");
Expect.isFalse(im.isGetter, "$name:isGetter");
Expect.equals(1, im.positionalArguments.length, "$name:#positional");
Expect.equals(
positional[0], im.positionalArguments[0], "$name:positional[0]");
Expect.equals(0, im.namedArguments.length, "$name:#named");
return;
}
Map<Symbol, dynamic> namedArguments = listToNamedArguments(named);
Expect.isTrue(im.isMethod, "$name:isMethod");
Expect.isFalse(im.isAccessor, "$name:isAccessor");
Expect.isFalse(im.isSetter, "$name:isSetter");
Expect.isFalse(im.isGetter, "$name:isGetter");
Expect.listEquals(positional, im.positionalArguments);
Expect.equals(
namedArguments.length, im.namedArguments.length, "$name:#named");
namedArguments.forEach((k, v) {
Expect.isTrue(
im.namedArguments.containsKey(k), "$name:?namedArguments[$k]");
Expect.equals(v, im.namedArguments[k], "$name:namedArguments[$k]");
});
}
// Test different ways that noSuchMethod can be called.
testInvocationMirrors() {
var n = new N();
var c = new C();
// Missing property/method access.
testInvocationMirror(n.bar, const Symbol('bar'));
testInvocationMirror((n..bar = 42).last, const Symbol('bar='), [42]);
testInvocationMirror(n.bar(), const Symbol('bar'), [], []);
testInvocationMirror(n.bar(42), const Symbol('bar'), [42], []);
testInvocationMirror(
n.bar(x: 42), const Symbol('bar'), [], [const Symbol("x"), 42]);
testInvocationMirror(
n.bar(37, x: 42), const Symbol('bar'), [37], [const Symbol("x"), 42]);
// Missing operator access.
testInvocationMirror(n + 4, const Symbol('+'), [4], []);
testInvocationMirror(n - 4, const Symbol('-'), [4], []);
testInvocationMirror(-n, const Symbol('unary-'), [], []);
testInvocationMirror(n[42], const Symbol('[]'), [42], []);
testInvocationMirror((n..[37] = 42).last, const Symbol('[]='), [37, 42], []);
// Calling as function when it's not.
testInvocationMirror(n(), const Symbol('call'), [], []);
testInvocationMirror(n(42), const Symbol('call'), [42], []);
testInvocationMirror(
n(x: 42), const Symbol('call'), [], [const Symbol("x"), 42]);
testInvocationMirror(
n(37, x: 42), const Symbol('call'), [37], [const Symbol("x"), 42]);
// Calling with arguments not matching existing call method.
testInvocationMirror(c(), const Symbol('call'), [], []);
testInvocationMirror(c(37, 42), const Symbol('call'), [37, 42], []);
testInvocationMirror(
c(x: 42), const Symbol('call'), [], [const Symbol("x"), 42]);
testInvocationMirror(
c(37, x: 42), const Symbol('call'), [37], [const Symbol("x"), 42]);
// Wrong arguments to existing function.
testInvocationMirror(n.flif(), const Symbol("flif"), [], []);
testInvocationMirror(n.flif(37, 42), const Symbol("flif"), [37, 42], []);
testInvocationMirror(
n.flif(x: 42), const Symbol("flif"), [], [const Symbol("x"), 42]);
testInvocationMirror(
n.flif(37, x: 42), const Symbol("flif"), [37], [const Symbol("x"), 42]);
testInvocationMirror((n..flif = 42).last, const Symbol("flif="), [42]);
testInvocationMirror(n.flaf(37, 42), const Symbol("flaf"), [37, 42], []);
testInvocationMirror(
n.flaf(x: 42), const Symbol("flaf"), [], [const Symbol("x"), 42]);
testInvocationMirror(
n.flaf(37, x: 42), const Symbol("flaf"), [37], [const Symbol("x"), 42]);
testInvocationMirror((n..flaf = 42).last, const Symbol("flaf="), [42]);
testInvocationMirror(n.flof(37, 42), const Symbol("flof"), [37, 42], []);
testInvocationMirror(
n.flof(x: 42), const Symbol("flof"), [], [const Symbol("x"), 42]);
testInvocationMirror(
n.flof(37, y: 42), const Symbol("flof"), [37], [const Symbol("y"), 42]);
testInvocationMirror((n..flof = 42).last, const Symbol("flof="), [42]);
// Reading works.
Expect.isTrue(n.flif is Function);
Expect.isTrue(n.flaf is Function);
Expect.isTrue(n.flof is Function);
// Writing to read-only fields.
testInvocationMirror((n..wut = 42).last, const Symbol("wut="), [42]);
testInvocationMirror((n..plif = 42).last, const Symbol("plif="), [42]);
testInvocationMirror((n..plaf = 42).last, const Symbol("plaf="), [42]);
// Trick call to n.call - wut is a getter returning n again.
testInvocationMirror(n.wut(42), const Symbol("call"), [42], []);
// Calling noSuchMethod itself, badly.
testInvocationMirror(n.noSuchMethod(), const Symbol("noSuchMethod"), [], []);
testInvocationMirror(
n.noSuchMethod(37, 42), const Symbol("noSuchMethod"), [37, 42], []);
testInvocationMirror(n.noSuchMethod(37, x: 42), const Symbol("noSuchMethod"),
[37], [const Symbol("x"), 42]);
testInvocationMirror(n.noSuchMethod(x: 42), const Symbol("noSuchMethod"), [],
[const Symbol("x"), 42]);
// Closurizing a method means that calling it badly will not hit the
// original receivers noSuchMethod, only the one inherited from Object
// by the closure object.
Expect.throws(() {
var x = n.flif;
x(37, 42);
}, (e) => e is NoSuchMethodError);
Expect.throws(() {
var x = c.call;
x(37, 42);
}, (e) => e is NoSuchMethodError);
}
class M extends N {
noSuchMethod(Invocation m) {
throw "never get here";
}
testSuperCalls() {
// Missing property/method access.
testInvocationMirror(super.bar, const Symbol('bar'));
testInvocationMirror(() {
super.bar = 42;
return last;
}(), const Symbol('bar='), [42]);
testInvocationMirror(super.bar(), const Symbol('bar'), [], []);
testInvocationMirror(super.bar(42), const Symbol('bar'), [42], []);
testInvocationMirror(
super.bar(x: 42), const Symbol('bar'), [], [const Symbol("x"), 42]);
testInvocationMirror(super.bar(37, x: 42), const Symbol('bar'), [37],
[const Symbol("x"), 42]);
// Missing operator access.
testInvocationMirror(super + 4, const Symbol('+'), [4], []);
testInvocationMirror(super - 4, const Symbol('-'), [4], []);
testInvocationMirror(-super, const Symbol('unary-'), [], []);
testInvocationMirror(super[42], const Symbol('[]'), [42], []);
testInvocationMirror(() {
super[37] = 42;
return last;
}(), const Symbol('[]='), [37, 42], []);
// Wrong arguments to existing function.
testInvocationMirror(super.flif(), const Symbol("flif"), [], []);
testInvocationMirror(
super.flif(37, 42), const Symbol("flif"), [37, 42], []);
testInvocationMirror(
super.flif(x: 42), const Symbol("flif"), [], [const Symbol("x"), 42]);
testInvocationMirror(super.flif(37, x: 42), const Symbol("flif"), [37],
[const Symbol("x"), 42]);
testInvocationMirror(() {
super.flif = 42;
return last;
}(), const Symbol("flif="), [42]);
testInvocationMirror(
super.flaf(37, 42), const Symbol("flaf"), [37, 42], []);
testInvocationMirror(
super.flaf(x: 42), const Symbol("flaf"), [], [const Symbol("x"), 42]);
testInvocationMirror(super.flaf(37, x: 42), const Symbol("flaf"), [37],
[const Symbol("x"), 42]);
testInvocationMirror(() {
super.flaf = 42;
return last;
}(), const Symbol("flaf="), [42]);
testInvocationMirror(
super.flof(37, 42), const Symbol("flof"), [37, 42], []);
testInvocationMirror(
super.flof(x: 42), const Symbol("flof"), [], [const Symbol("x"), 42]);
testInvocationMirror(super.flof(37, y: 42), const Symbol("flof"), [37],
[const Symbol("y"), 42]);
testInvocationMirror(() {
super.flof = 42;
return last;
}(), const Symbol("flof="), [42]);
// Reading works.
Expect.isTrue(super.flif is Function);
Expect.isTrue(super.flaf is Function);
Expect.isTrue(super.flof is Function);
// Writing to read-only fields.
testInvocationMirror(() {
super.wut = 42;
return last;
}(), const Symbol("wut="), [42]);
testInvocationMirror(() {
super.plif = 42;
return last;
}(), const Symbol("plif="), [42]);
testInvocationMirror(() {
super.plaf = 42;
return last;
}(), const Symbol("plaf="), [42]);
// Calling noSuchMethod itself, badly.
testInvocationMirror(
super.noSuchMethod(), const Symbol("noSuchMethod"), [], []);
testInvocationMirror(
super.noSuchMethod(37, 42), const Symbol("noSuchMethod"), [37, 42], []);
testInvocationMirror(super.noSuchMethod(37, x: 42),
const Symbol("noSuchMethod"), [37], [const Symbol("x"), 42]);
testInvocationMirror(super.noSuchMethod(x: 42),
const Symbol("noSuchMethod"), [], [const Symbol("x"), 42]);
// Closurizing a method means that calling it badly will not hit the
// original receivers noSuchMethod, only the one inherited from Object
// by the closure object.
Expect.throws(() {
var x = super.flif;
x(37, 42);
}, (e) => e is NoSuchMethodError);
}
}
// Test the NoSuchMethodError thrown by different incorrect calls.
testNoSuchMethodErrors() {
test(Function block) {
Expect.throws(block, (e) => e is NoSuchMethodError);
}
var n = new N();
var o = new Object();
test(() => o.bar);
test(() => o.bar = 42);
test(() => o.bar());
test(() => o + 2);
test(() => -o);
test(() => o[0]);
test(() => o[0] = 42);
test(() => o());
test(() => o.toString = 42);
test(() => o.toString(42));
test(() => o.toString(x: 37));
test(() => o.hashCode = 42);
test(() => o.hashCode()); // Thrown by int.noSuchMethod.
test(() => (n.flif)()); // Extracted method has no noSuchMethod.
}
main() {
testInvocationMirrors();
testNoSuchMethodErrors();
new M().testSuperCalls();
}