diff --git a/lib/web_ui/test/engine/canvas_test.dart b/lib/web_ui/test/engine/canvas_test.dart index 053cd9c155b6b..926ac1b3fe339 100644 --- a/lib/web_ui/test/engine/canvas_test.dart +++ b/lib/web_ui/test/engine/canvas_test.dart @@ -11,6 +11,8 @@ import 'package:ui/src/engine.dart'; import 'package:ui/ui.dart' as ui; +import '../matchers.dart'; + void main() { internalBootstrapBrowserTest(() => testMain); } @@ -31,7 +33,7 @@ void runCanvasTests({required bool deviceClipRoundsOut}) { expect(value.length, equals(16)); for (int r = 0; r < 4; r++) { for (int c = 0; c < 4; c++) { - expect(value[r*4 + c], closeTo(expected[r*4 + c], 1e-10)); + expect(value[r*4 + c], within(from: expected[r*4 + c])); } } } diff --git a/lib/web_ui/test/geometry_test.dart b/lib/web_ui/test/geometry_test.dart index 24150d801cdf4..80df3611c3af8 100644 --- a/lib/web_ui/test/geometry_test.dart +++ b/lib/web_ui/test/geometry_test.dart @@ -13,6 +13,8 @@ import 'package:test/test.dart'; import 'package:ui/ui.dart'; +import 'matchers.dart'; + void main() { internalBootstrapBrowserTest(() => testMain); } @@ -31,34 +33,32 @@ void testMain() { }); test('Offset.fromDirection', () { expect(Offset.fromDirection(0.0, 0.0), const Offset(0.0, 0.0)); - expect(Offset.fromDirection(pi / 2.0).dx, - closeTo(0.0, 1e-12)); // aah, floating point math. i love you so. - expect(Offset.fromDirection(pi / 2.0).dy, 1.0); - expect(Offset.fromDirection(-pi / 2.0).dx, closeTo(0.0, 1e-12)); - expect(Offset.fromDirection(-pi / 2.0).dy, -1.0); + // aah, floating point math. i love you so. + expect(Offset.fromDirection(pi / 2.0), within(from: const Offset(0.0, 1.0))); + expect(Offset.fromDirection(-pi / 2.0), within(from: const Offset(0.0, -1.0))); expect(Offset.fromDirection(0.0), const Offset(1.0, 0.0)); - expect(Offset.fromDirection(pi / 4.0).dx, - closeTo(1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(pi / 4.0).dy, - closeTo(1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(-pi / 4.0).dx, - closeTo(1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(-pi / 4.0).dy, - closeTo(-1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(pi).dx, -1.0); - expect(Offset.fromDirection(pi).dy, closeTo(0.0, 1e-12)); - expect(Offset.fromDirection(pi * 3.0 / 4.0).dx, - closeTo(-1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(pi * 3.0 / 4.0).dy, - closeTo(1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(-pi * 3.0 / 4.0).dx, - closeTo(-1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(-pi * 3.0 / 4.0).dy, - closeTo(-1.0 / math.sqrt(2.0), 1e-12)); + expect( + Offset.fromDirection(pi / 4.0), + within(from: Offset(1.0 / math.sqrt(2.0), 1.0 / math.sqrt(2.0))), + ); + expect( + Offset.fromDirection(-pi / 4.0), + within(from: Offset(1.0 / math.sqrt(2.0), -1.0 / math.sqrt(2.0))), + ); + expect(Offset.fromDirection(pi), within(from: const Offset(-1.0, 0.0))); + expect( + Offset.fromDirection(pi * 3.0 / 4.0), + within(from: Offset(-1.0 / math.sqrt(2.0), 1.0 / math.sqrt(2.0))), + ); + expect( + Offset.fromDirection(-pi * 3.0 / 4.0), + within(from: Offset(-1.0 / math.sqrt(2.0), -1.0 / math.sqrt(2.0))), + ); expect(Offset.fromDirection(0.0, 2.0), const Offset(2.0, 0.0)); expect( - Offset.fromDirection(pi / 6, 2.0).dx, closeTo(math.sqrt(3.0), 1e-12)); - expect(Offset.fromDirection(pi / 6, 2.0).dy, closeTo(1.0, 1e-12)); + Offset.fromDirection(pi / 6, 2.0), + within(from: Offset(math.sqrt(3.0), 1.0)), + ); }); test('Size.aspectRatio', () { expect(const Size(0.0, 0.0).aspectRatio, 0.0); diff --git a/lib/web_ui/test/lerp_test.dart b/lib/web_ui/test/lerp_test.dart index 2c9d1fc0574c0..65dde6513fbd7 100644 --- a/lib/web_ui/test/lerp_test.dart +++ b/lib/web_ui/test/lerp_test.dart @@ -7,12 +7,7 @@ import 'package:test/test.dart'; import 'package:ui/ui.dart'; -/// The epsilon of tolerable double precision error. -/// -/// This is used in various places in the framework to allow for floating point -/// precision loss in calculations. Differences below this threshold are safe -/// to disregard. -const double precisionErrorTolerance = 1e-10; +import 'matchers.dart'; void main() { internalBootstrapBrowserTest(() => testMain); @@ -31,19 +26,19 @@ void testMain() { }); test('lerpDouble should treat a null input as 0 if the other input is non-null', () { - expect(lerpDouble(null, 10.0, 0.25), closeTo(2.5, precisionErrorTolerance)); - expect(lerpDouble(10.0, null, 0.25), closeTo(7.5, precisionErrorTolerance)); + expect(lerpDouble(null, 10.0, 0.25), within(from: 2.5)); + expect(lerpDouble(10.0, null, 0.25), within(from: 7.5)); - expect(lerpDouble(null, 10, 0.25), closeTo(2.5, precisionErrorTolerance)); - expect(lerpDouble(10, null, 0.25), closeTo(7.5, precisionErrorTolerance)); + expect(lerpDouble(null, 10, 0.25), within(from: 2.5)); + expect(lerpDouble(10, null, 0.25), within(from: 7.5)); }); test('lerpDouble should handle interpolation values < 0.0', () { - expect(lerpDouble(0.0, 10.0, -5.0), closeTo(-50.0, precisionErrorTolerance)); - expect(lerpDouble(10.0, 0.0, -5.0), closeTo(60.0, precisionErrorTolerance)); + expect(lerpDouble(0.0, 10.0, -5.0), within(from: -50.0)); + expect(lerpDouble(10.0, 0.0, -5.0), within(from: 60.0)); - expect(lerpDouble(0, 10, -5), closeTo(-50, precisionErrorTolerance)); - expect(lerpDouble(10, 0, -5), closeTo(60, precisionErrorTolerance)); + expect(lerpDouble(0, 10, -5), within(from: -50.0)); + expect(lerpDouble(10, 0, -5), within(from: 60.0)); }); test('lerpDouble should return the start value at 0.0', () { @@ -55,17 +50,17 @@ void testMain() { }); test('lerpDouble should interpolate between two values', () { - expect(lerpDouble(0.0, 10.0, 0.25), closeTo(2.5, precisionErrorTolerance)); - expect(lerpDouble(10.0, 0.0, 0.25), closeTo(7.5, precisionErrorTolerance)); + expect(lerpDouble(0.0, 10.0, 0.25), within(from: 2.5)); + expect(lerpDouble(10.0, 0.0, 0.25), within(from: 7.5)); - expect(lerpDouble(0, 10, 0.25), closeTo(2.5, precisionErrorTolerance)); - expect(lerpDouble(10, 0, 0.25), closeTo(7.5, precisionErrorTolerance)); + expect(lerpDouble(0, 10, 0.25), within(from: 2.5)); + expect(lerpDouble(10, 0, 0.25), within(from: 7.5)); // Exact answer: 20.0 - 1.0e-29 - expect(lerpDouble(10.0, 1.0e30, 1.0e-29), closeTo(20.0, precisionErrorTolerance)); + expect(lerpDouble(10.0, 1.0e30, 1.0e-29), within(from: 20.0)); // Exact answer: 5.0 + 5.0e29 - expect(lerpDouble(10.0, 1.0e30, 0.5), closeTo(5.0e29, precisionErrorTolerance)); + expect(lerpDouble(10.0, 1.0e30, 0.5), within(from: 5.0e29)); }); test('lerpDouble should return the end value at 1.0', () { @@ -80,11 +75,11 @@ void testMain() { }); test('lerpDouble should handle interpolation values > 1.0', () { - expect(lerpDouble(0.0, 10.0, 5.0), closeTo(50.0, precisionErrorTolerance)); - expect(lerpDouble(10.0, 0.0, 5.0), closeTo(-40.0, precisionErrorTolerance)); + expect(lerpDouble(0.0, 10.0, 5.0), within(from: 50.0)); + expect(lerpDouble(10.0, 0.0, 5.0), within(from: -40.0)); - expect(lerpDouble(0, 10, 5), closeTo(50, precisionErrorTolerance)); - expect(lerpDouble(10, 0, 5), closeTo(-40, precisionErrorTolerance)); + expect(lerpDouble(0, 10, 5), within(from: 50.0)); + expect(lerpDouble(10, 0, 5), within(from: -40.0)); }); test('lerpDouble should return input value in all cases if begin/end are equal', () { diff --git a/lib/web_ui/test/matchers.dart b/lib/web_ui/test/matchers.dart index 6278fa2cfe65f..df6124d0790d5 100644 --- a/lib/web_ui/test/matchers.dart +++ b/lib/web_ui/test/matchers.dart @@ -15,6 +15,13 @@ import 'package:test/test.dart'; import 'package:ui/src/engine.dart'; import 'package:ui/ui.dart'; +/// The epsilon of tolerable double precision error. +/// +/// This is used in various places in the framework to allow for floating point +/// precision loss in calculations. Differences below this threshold are safe +/// to disregard. +const double precisionErrorTolerance = 1e-10; + /// Enumerates all persisted surfaces in the tree rooted at [root]. /// /// If [root] is `null` returns all surfaces from the last rendered scene. @@ -60,7 +67,7 @@ Iterable enumerateOffsets([PersistedSurface? root]) { /// /// This makes it useful for comparing numbers, [Color]s, [Offset]s and other /// sets of value for which a metric space is defined. -typedef DistanceFunction = num Function(T a, T b); +typedef DistanceFunction = double Function(T a, T b); /// The type of a union of instances of [DistanceFunction] for various types /// T. @@ -73,7 +80,7 @@ typedef DistanceFunction = num Function(T a, T b); /// /// Calling an instance of this type must either be done dynamically, or by /// first casting it to a [DistanceFunction] for some concrete T. -typedef AnyDistanceFunction = num Function(Never a, Never b); +typedef AnyDistanceFunction = double Function(Never a, Never b); const Map _kStandardDistanceFunctions = { @@ -85,7 +92,7 @@ const Map _kStandardDistanceFunctions = Size: _sizeDistance, }; -int _intDistance(int a, int b) => (b - a).abs(); +double _intDistance(int a, int b) => (b - a).abs().toDouble(); double _doubleDistance(double a, double b) => (b - a).abs(); double _offsetDistance(Offset a, Offset b) => (b - a).distance; @@ -131,8 +138,8 @@ double _sizeDistance(Size a, Size b) { /// [double]s and has an optional `epsilon` parameter. /// * [closeTo], which specializes in numbers only. Matcher within({ - required num distance, required T from, + double distance = precisionErrorTolerance, DistanceFunction? distanceFunction, }) { distanceFunction ??= _kStandardDistanceFunctions[T] as DistanceFunction?; @@ -152,7 +159,7 @@ class _IsWithinDistance extends Matcher { final DistanceFunction distanceFunction; final T value; - final num epsilon; + final double epsilon; @override bool matches(Object? object, Map matchState) { @@ -163,7 +170,7 @@ class _IsWithinDistance extends Matcher { return true; } final T test = object; - final num distance = distanceFunction(test, value); + final double distance = distanceFunction(test, value); if (distance < 0) { throw ArgumentError( 'Invalid distance function was used to compare a ${value.runtimeType} '