blob: 4811a87d515d72e9870c640fb57f6edfad72dfd3 [file] [log] [blame]
// Copyright (c) 2020, 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.
// This library defines a set of test functions 'xxxAsBoolean" and a check
// combinator called `check` which test the runtime behavior of conversions
// of values in boolean condional positions (e.g. the condition of a conditional
// statement).
//
// For example: calling `check(dynamicAsBoolean, value, expectation)` tests that
// using `value` as the condition in a number of different syntactic constructs
// with static type `dynamic` behaves as expected by `expectation`, where
// `expectation` should be one of:
// Expect.throwsAssertionError if a null conversion error is expected
// Expect.throwsTypeError if an implicit cast error is expected
// expectOk if no runtime error is expected.
void expectOk(void Function() f) {
f();
}
final int constructsTested = 11;
void check<T>(void Function(T, int) test, T value,
void Function(void Function()) expectation) {
for (int i = 0; i < constructsTested; i++) {
expectation(() => test(value, i));
}
}
void neverAsBoolean(Never value, int index) {
// Check that values of type `Never` are boolean converted appropriately
// In strong checking mode, this code is unreachable. In weak checking mode,
// we may get passed `null` for `value`, and so we check that the `null` value
// causes an assertion error to be thrown appropriately.
switch (index) {
case 0:
if (value) {}
break;
case 1:
[if (value) 3];
break;
case 2:
value ? 3 : 4;
break;
case 3:
while (value) {
break;
}
break;
case 4:
var done = false;
do {
if (done) break;
done = true;
} while (value);
break;
case 5:
value || true;
break;
case 6:
value && true;
break;
case 7:
false || value;
break;
case 8:
true && value;
break;
case 9:
for (int i = 0; value; i++) {
break;
}
break;
case 10:
[for (int i = 0; value; i++) 3];
break;
default:
throw "Invalid index";
}
}
void booleanAsBoolean(bool value, int index) {
// Check that values of type `boolean` are boolean converted appropriately
switch (index) {
case 0:
if (value) {}
break;
case 1:
[if (value) 3];
break;
case 2:
value ? 3 : 4;
break;
case 3:
while (value) {
break;
}
break;
case 4:
var done = false;
do {
if (done) break;
done = true;
} while (value);
break;
case 5:
value || true;
break;
case 6:
value && true;
break;
case 7:
false || value;
break;
case 8:
true && value;
break;
case 9:
for (int i = 0; value; i++) {
break;
}
break;
case 10:
[for (int i = 0; value; value = false) 3];
break;
default:
throw "Invalid index";
}
}
void dynamicAsBoolean(dynamic value, int index) {
// Check that values of type `dynamic` are boolean converted appropriately
switch (index) {
case 0:
if (value) {}
break;
case 1:
[if (value) 3];
break;
case 2:
value ? 3 : 4;
break;
case 3:
while (value) {
break;
}
break;
case 4:
var done = false;
do {
if (done) break;
done = true;
} while (value);
break;
case 5:
value || true;
break;
case 6:
value && true;
break;
case 7:
false || value;
break;
case 8:
true && value;
break;
case 9:
for (int i = 0; value; i++) {
break;
}
break;
case 10:
[for (int i = 0; value; value = false) 3];
break;
default:
throw "Invalid index";
}
}