Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/web_ui/test/engine/canvas_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import 'package:ui/src/engine.dart';

import 'package:ui/ui.dart' as ui;

import '../matchers.dart';

void main() {
internalBootstrapBrowserTest(() => testMain);
}
Expand All @@ -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]));
}
}
}
Expand Down
50 changes: 25 additions & 25 deletions lib/web_ui/test/geometry_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import 'package:test/test.dart';

import 'package:ui/ui.dart';

import 'matchers.dart';

void main() {
internalBootstrapBrowserTest(() => testMain);
}
Expand All @@ -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);
Expand Down
43 changes: 19 additions & 24 deletions lib/web_ui/test/lerp_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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));
expect(lerpDouble(10, 0, -5), within(from: 60));
});

test('lerpDouble should return the start value at 0.0', () {
Expand All @@ -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', () {
Expand All @@ -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));
expect(lerpDouble(10, 0, 5), within(from: -40));
});

test('lerpDouble should return input value in all cases if begin/end are equal', () {
Expand Down
17 changes: 12 additions & 5 deletions lib/web_ui/test/matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -60,7 +67,7 @@ Iterable<PersistedOffset> 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<T> = num Function(T a, T b);
typedef DistanceFunction<T> = double Function(T a, T b);

/// The type of a union of instances of [DistanceFunction<T>] for various types
/// T.
Expand All @@ -85,7 +92,7 @@ const Map<Type, AnyDistanceFunction> _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;

Expand Down Expand Up @@ -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<T>({
required num distance,
required T from,
double distance = precisionErrorTolerance,
DistanceFunction<T>? distanceFunction,
}) {
distanceFunction ??= _kStandardDistanceFunctions[T] as DistanceFunction<T>?;
Expand All @@ -152,7 +159,7 @@ class _IsWithinDistance<T> extends Matcher {

final DistanceFunction<T> distanceFunction;
final T value;
final num epsilon;
final double epsilon;

@override
bool matches(Object? object, Map<dynamic, dynamic> matchState) {
Expand All @@ -163,7 +170,7 @@ class _IsWithinDistance<T> 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} '
Expand Down