dart-sdk/tests/language_2/generic_function_bounds_test.dart
Kevin Millikin fa1d2c896d Fix order of arguments to Expect.equals in some tests
Expect.equals (and Expect.listEquals) takes expected first and actual
second.  When these are flipped in tests, the failure message can be super
hard to understand.

Bug:
Change-Id: I1d3c5a31365fa41ee7bcc7781474d76de9184cd5
Reviewed-on: https://dart-review.googlesource.com/23420
Reviewed-by: Jonas Termansen <sortie@google.com>
Commit-Queue: Kevin Millikin <kmillikin@google.com>
2017-11-23 14:45:46 +00:00

79 lines
2.6 KiB
Dart

// Copyright (c) 2017, 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 'dart:math';
import 'package:expect/expect.dart';
void testInstantiateToBounds() {
f<T extends num, U extends T>() => [T, U];
g<T extends List<U>, U extends int>() => [T, U];
h<T extends num, U extends T>(T x, U y) => h.runtimeType.toString();
Expect.listEquals([num, num], (f as dynamic)());
Expect.equals('List<int>|int', (g as dynamic)().join('|'));
Expect.equals('<T extends num, U extends T>(T, U) => String',
(h as dynamic)(null, null));
i<T extends Iterable<T>>() => null;
j<T extends Iterable<S>, S extends T>() => null;
Expect.throws(
() => (i as dynamic)(), (e) => '$e'.contains('Instantiate to bounds'));
Expect.throws(
() => (j as dynamic)(), (e) => '$e'.contains('Instantiate to bounds'));
}
void testChecksBound() {
f<T extends num>(T x) => x;
Expect.equals((f as dynamic)(42), 42);
Expect.throws(() => (f as dynamic)('42'));
msg(t1, t2, tf) => Expect.throws(() => (f as dynamic)<Object>(42),
(e) => '$e' == 'type `Object` does not extend `num` of `T');
g<T extends U, U extends num>(T x, U y) => x;
Expect.equals((g as dynamic)(42.0, 100), 42.0);
Expect.throws(() => (g as dynamic)('hi', 100));
Expect.throws(() => (g as dynamic)<double, int>(42.0, 100),
(e) => '$e' == 'type `double` does not extend `int` of `T`.');
Expect.throws(() => (g as dynamic)<num, Object>(42.0, 100),
(e) => '$e' == 'type `Object` does not extend `num` of `U`.');
}
typedef G<U> = T Function<T extends U>(T x);
void testSubtype() {
f<T extends num>(T x) => x + 2;
dynamic d = f;
Expect.equals(d(40.0), 42.0);
Expect.equals((f as G<int>)(40), 42);
Expect.equals((d as G<int>)(40), 42);
Expect.equals((f as G<double>)(40.0), 42.0);
Expect.equals((d as G<double>)(40.0), 42.0);
d as G<Null>;
Expect.throws(() => d as G);
Expect.throws(() => d as G<Object>);
Expect.throws(() => d as G<String>);
}
void testToString() {
// TODO(jmesserly): I don't think the cast on `y` should be required.
num f<T extends num, U extends T>(T x, U y) => min(x, y as num);
num g<T, U>(T x, U y) => max(x as num, y as num);
String h<T, U>(T x, U y) => h.runtimeType.toString();
Expect.equals(
f.runtimeType.toString(), '<T extends num, U extends T>(T, U) => num');
Expect.equals(g.runtimeType.toString(), '<T, U>(T, U) => num');
Expect.equals(h(42, 123.0), '<T, U>(T, U) => String');
}
main() {
testInstantiateToBounds();
testToString();
testChecksBound();
testSubtype();
}