Reverts flutter/flutter#137381 Initiated by: Piinks This change reverts the following previous change: Original Description: This updates the implementation to use the stopwatch from the Clock object and piping it through to the TestWidgetsFlutterBinding so it will be kept in sync with FakeAsync. Relands #132291 Fixes https://github.com/flutter/flutter/issues/97761 The change was reverted due to flakiness it introduced in tests that use fling gestures. * https://github.com/flutter/flutter/issues/135728
This commit is contained in:
parent
465288588f
commit
82a7a62b45
@ -366,7 +366,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
|
||||
|
||||
if (resamplingEnabled) {
|
||||
_resampler.addOrDispatch(event);
|
||||
_resampler.sample(samplingOffset, samplingClock);
|
||||
_resampler.sample(samplingOffset, _samplingClock);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -505,10 +505,16 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
|
||||
_hitTests.clear();
|
||||
}
|
||||
|
||||
/// Overrides the sampling clock for debugging and testing.
|
||||
///
|
||||
/// This value is ignored in non-debug builds.
|
||||
@protected
|
||||
SamplingClock? get debugSamplingClock => null;
|
||||
|
||||
void _handleSampleTimeChanged() {
|
||||
if (!locked) {
|
||||
if (resamplingEnabled) {
|
||||
_resampler.sample(samplingOffset, samplingClock);
|
||||
_resampler.sample(samplingOffset, _samplingClock);
|
||||
}
|
||||
else {
|
||||
_resampler.stop();
|
||||
@ -516,18 +522,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
|
||||
}
|
||||
}
|
||||
|
||||
/// Overrides the [samplingClock] for debugging and testing.
|
||||
///
|
||||
/// This value is ignored in non-debug builds.
|
||||
@protected
|
||||
SamplingClock? get debugSamplingClock => null;
|
||||
|
||||
/// Provides access to the current [DateTime] and `StopWatch` objects for
|
||||
/// sampling.
|
||||
///
|
||||
/// Overridden by [debugSamplingClock] for debug builds and testing. Using
|
||||
/// this object under test will maintain synchronization with [FakeAsync].
|
||||
SamplingClock get samplingClock {
|
||||
SamplingClock get _samplingClock {
|
||||
SamplingClock value = SamplingClock();
|
||||
assert(() {
|
||||
final SamplingClock? debugValue = debugSamplingClock;
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'binding.dart';
|
||||
import 'events.dart';
|
||||
import 'lsq_solver.dart';
|
||||
|
||||
@ -150,21 +149,12 @@ class VelocityTracker {
|
||||
/// The kind of pointer this tracker is for.
|
||||
final PointerDeviceKind kind;
|
||||
|
||||
// Time difference since the last sample was added
|
||||
Stopwatch get _sinceLastSample {
|
||||
_stopwatch ??= GestureBinding.instance.samplingClock.stopwatch();
|
||||
return _stopwatch!;
|
||||
}
|
||||
Stopwatch? _stopwatch;
|
||||
|
||||
// Circular buffer; current sample at _index.
|
||||
final List<_PointAtTime?> _samples = List<_PointAtTime?>.filled(_historySize, null);
|
||||
int _index = 0;
|
||||
|
||||
/// Adds a position as the given time to the tracker.
|
||||
void addPosition(Duration time, Offset position) {
|
||||
_sinceLastSample.start();
|
||||
_sinceLastSample.reset();
|
||||
_index += 1;
|
||||
if (_index == _historySize) {
|
||||
_index = 0;
|
||||
@ -179,16 +169,6 @@ class VelocityTracker {
|
||||
///
|
||||
/// Returns null if there is no data on which to base an estimate.
|
||||
VelocityEstimate? getVelocityEstimate() {
|
||||
// Has user recently moved since last sample?
|
||||
if (_sinceLastSample.elapsedMilliseconds > VelocityTracker._assumePointerMoveStoppedMilliseconds) {
|
||||
return const VelocityEstimate(
|
||||
pixelsPerSecond: Offset.zero,
|
||||
confidence: 1.0,
|
||||
duration: Duration.zero,
|
||||
offset: Offset.zero,
|
||||
);
|
||||
}
|
||||
|
||||
final List<double> x = <double>[];
|
||||
final List<double> y = <double>[];
|
||||
final List<double> w = <double>[];
|
||||
@ -215,7 +195,7 @@ class VelocityTracker {
|
||||
final double age = (newestSample.time - sample.time).inMicroseconds.toDouble() / 1000;
|
||||
final double delta = (sample.time - previousSample.time).inMicroseconds.abs().toDouble() / 1000;
|
||||
previousSample = sample;
|
||||
if (age > _horizonMilliseconds || delta > VelocityTracker._assumePointerMoveStoppedMilliseconds) {
|
||||
if (age > _horizonMilliseconds || delta > _assumePointerMoveStoppedMilliseconds) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -308,8 +288,6 @@ class IOSScrollViewFlingVelocityTracker extends VelocityTracker {
|
||||
|
||||
@override
|
||||
void addPosition(Duration time, Offset position) {
|
||||
_sinceLastSample.start();
|
||||
_sinceLastSample.reset();
|
||||
assert(() {
|
||||
final _PointAtTime? previousPoint = _touchSamples[_index];
|
||||
if (previousPoint == null || previousPoint.time <= time) {
|
||||
@ -348,16 +326,6 @@ class IOSScrollViewFlingVelocityTracker extends VelocityTracker {
|
||||
|
||||
@override
|
||||
VelocityEstimate getVelocityEstimate() {
|
||||
// Has user recently moved since last sample?
|
||||
if (_sinceLastSample.elapsedMilliseconds > VelocityTracker._assumePointerMoveStoppedMilliseconds) {
|
||||
return const VelocityEstimate(
|
||||
pixelsPerSecond: Offset.zero,
|
||||
confidence: 1.0,
|
||||
duration: Duration.zero,
|
||||
offset: Offset.zero,
|
||||
);
|
||||
}
|
||||
|
||||
// The velocity estimated using this expression is an approximation of the
|
||||
// scroll velocity of an iOS scroll view at the moment the user touch was
|
||||
// released, not the final velocity of the iOS pan gesture recognizer
|
||||
@ -419,16 +387,6 @@ class MacOSScrollViewFlingVelocityTracker extends IOSScrollViewFlingVelocityTrac
|
||||
|
||||
@override
|
||||
VelocityEstimate getVelocityEstimate() {
|
||||
// Has user recently moved since last sample?
|
||||
if (_sinceLastSample.elapsedMilliseconds > VelocityTracker._assumePointerMoveStoppedMilliseconds) {
|
||||
return const VelocityEstimate(
|
||||
pixelsPerSecond: Offset.zero,
|
||||
confidence: 1.0,
|
||||
duration: Duration.zero,
|
||||
offset: Offset.zero,
|
||||
);
|
||||
}
|
||||
|
||||
// The velocity estimated using this expression is an approximation of the
|
||||
// scroll velocity of a macOS scroll view at the moment the user touch was
|
||||
// released.
|
||||
|
@ -4,18 +4,35 @@
|
||||
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:clock/clock.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
|
||||
|
||||
class TestResampleEventFlutterBinding extends AutomatedTestWidgetsFlutterBinding {
|
||||
@override
|
||||
SamplingClock? get debugSamplingClock => TestSamplingClock(this.clock);
|
||||
}
|
||||
|
||||
class TestSamplingClock implements SamplingClock {
|
||||
TestSamplingClock(this._clock);
|
||||
|
||||
@override
|
||||
DateTime now() => _clock.now();
|
||||
|
||||
@override
|
||||
Stopwatch stopwatch() => _clock.stopwatch();
|
||||
|
||||
final Clock _clock;
|
||||
}
|
||||
|
||||
void main() {
|
||||
final TestWidgetsFlutterBinding binding = TestResampleEventFlutterBinding();
|
||||
testWidgetsWithLeakTracking('PointerEvent resampling on a widget', (WidgetTester tester) async {
|
||||
Duration currentTestFrameTime() => Duration(
|
||||
milliseconds: TestWidgetsFlutterBinding.instance.clock.now().millisecondsSinceEpoch,
|
||||
);
|
||||
assert(WidgetsBinding.instance == binding);
|
||||
Duration currentTestFrameTime() => Duration(milliseconds: binding.clock.now().millisecondsSinceEpoch);
|
||||
void requestFrame() => SchedulerBinding.instance.scheduleFrameCallback((_) {});
|
||||
final Duration epoch = currentTestFrameTime();
|
||||
final ui.PointerDataPacket packet = ui.PointerDataPacket(
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
import 'package:fake_async/fake_async.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
class GestureTester {
|
||||
@ -26,7 +26,7 @@ typedef GestureTest = void Function(GestureTester tester);
|
||||
|
||||
@isTest
|
||||
void testGesture(String description, GestureTest callback) {
|
||||
testWidgetsWithLeakTracking(description, (_) async {
|
||||
test(description, () {
|
||||
FakeAsync().run((FakeAsync async) {
|
||||
callback(GestureTester._(async));
|
||||
});
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
|
||||
import 'velocity_tracker_data.dart';
|
||||
|
||||
bool _withinTolerance(double actual, double expected) {
|
||||
@ -35,7 +34,7 @@ void main() {
|
||||
Offset(-71.51939428321249, 3716.7385187526947),
|
||||
];
|
||||
|
||||
testWidgetsWithLeakTracking('Velocity tracker gives expected results', (WidgetTester tester) async {
|
||||
test('Velocity tracker gives expected results', () {
|
||||
final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch);
|
||||
int i = 0;
|
||||
for (final PointerEvent event in velocityEventData) {
|
||||
@ -49,7 +48,7 @@ void main() {
|
||||
}
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('Velocity control test', (WidgetTester tester) async {
|
||||
test('Velocity control test', () {
|
||||
const Velocity velocity1 = Velocity(pixelsPerSecond: Offset(7.0, 0.0));
|
||||
const Velocity velocity2 = Velocity(pixelsPerSecond: Offset(12.0, 0.0));
|
||||
expect(velocity1, equals(const Velocity(pixelsPerSecond: Offset(7.0, 0.0))));
|
||||
@ -61,7 +60,7 @@ void main() {
|
||||
expect(velocity1, hasOneLineDescription);
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('Interrupted velocity estimation', (WidgetTester tester) async {
|
||||
test('Interrupted velocity estimation', () {
|
||||
// Regression test for https://github.com/flutter/flutter/pull/7510
|
||||
final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch);
|
||||
for (final PointerEvent event in interruptedVelocityEventData) {
|
||||
@ -74,12 +73,12 @@ void main() {
|
||||
}
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('No data velocity estimation', (WidgetTester tester) async {
|
||||
test('No data velocity estimation', () {
|
||||
final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch);
|
||||
expect(tracker.getVelocity(), Velocity.zero);
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('FreeScrollStartVelocityTracker.getVelocity throws when no points', (WidgetTester tester) async {
|
||||
test('FreeScrollStartVelocityTracker.getVelocity throws when no points', () {
|
||||
final IOSScrollViewFlingVelocityTracker tracker = IOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch);
|
||||
AssertionError? exception;
|
||||
try {
|
||||
@ -91,7 +90,7 @@ void main() {
|
||||
expect(exception?.toString(), contains('at least 1 point'));
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('FreeScrollStartVelocityTracker.getVelocity throws when the new point precedes the previous point', (WidgetTester tester) async {
|
||||
test('FreeScrollStartVelocityTracker.getVelocity throws when the new point precedes the previous point', () {
|
||||
final IOSScrollViewFlingVelocityTracker tracker = IOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch);
|
||||
AssertionError? exception;
|
||||
|
||||
@ -106,7 +105,7 @@ void main() {
|
||||
expect(exception?.toString(), contains('has a smaller timestamp'));
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('Estimate does not throw when there are more than 1 point', (WidgetTester tester) async {
|
||||
test('Estimate does not throw when there are more than 1 point', () {
|
||||
final IOSScrollViewFlingVelocityTracker tracker = IOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch);
|
||||
Offset position = Offset.zero;
|
||||
Duration time = Duration.zero;
|
||||
@ -128,7 +127,7 @@ void main() {
|
||||
}
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('Makes consistent velocity estimates with consistent velocity', (WidgetTester tester) async {
|
||||
test('Makes consistent velocity estimates with consistent velocity', () {
|
||||
final IOSScrollViewFlingVelocityTracker tracker = IOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch);
|
||||
Offset position = Offset.zero;
|
||||
Duration time = Duration.zero;
|
||||
@ -145,55 +144,4 @@ void main() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('Assume zero velocity when there are no recent samples - base VelocityTracker', (WidgetTester tester) async {
|
||||
final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch);
|
||||
Offset position = Offset.zero;
|
||||
Duration time = Duration.zero;
|
||||
const Offset positionDelta = Offset(0, -1);
|
||||
const Duration durationDelta = Duration(seconds: 1);
|
||||
|
||||
for (int i = 0; i < 10; i+=1) {
|
||||
position += positionDelta;
|
||||
time += durationDelta;
|
||||
tracker.addPosition(time, position);
|
||||
}
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(tracker.getVelocity().pixelsPerSecond, Offset.zero);
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('Assume zero velocity when there are no recent samples - IOS', (WidgetTester tester) async {
|
||||
final IOSScrollViewFlingVelocityTracker tracker = IOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch);
|
||||
Offset position = Offset.zero;
|
||||
Duration time = Duration.zero;
|
||||
const Offset positionDelta = Offset(0, -1);
|
||||
const Duration durationDelta = Duration(seconds: 1);
|
||||
|
||||
for (int i = 0; i < 10; i+=1) {
|
||||
position += positionDelta;
|
||||
time += durationDelta;
|
||||
tracker.addPosition(time, position);
|
||||
}
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(tracker.getVelocity().pixelsPerSecond, Offset.zero);
|
||||
});
|
||||
|
||||
testWidgetsWithLeakTracking('Assume zero velocity when there are no recent samples - MacOS', (WidgetTester tester) async {
|
||||
final MacOSScrollViewFlingVelocityTracker tracker = MacOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch);
|
||||
Offset position = Offset.zero;
|
||||
Duration time = Duration.zero;
|
||||
const Offset positionDelta = Offset(0, -1);
|
||||
const Duration durationDelta = Duration(seconds: 1);
|
||||
|
||||
for (int i = 0; i < 10; i+=1) {
|
||||
position += positionDelta;
|
||||
time += durationDelta;
|
||||
tracker.addPosition(time, position);
|
||||
}
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(tracker.getVelocity().pixelsPerSecond, Offset.zero);
|
||||
});
|
||||
}
|
||||
|
@ -8,9 +8,9 @@ import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
final TestWidgetsFlutterBinding binding = _GestureBindingSpy();
|
||||
testWidgets('attach and detach correctly handle gesture', (_) async {
|
||||
assert(WidgetsBinding.instance == binding);
|
||||
setUp(() => _GestureBindingSpy());
|
||||
|
||||
test('attach and detach correctly handle gesture', () {
|
||||
final TextSelectionDelegate delegate = FakeEditableTextState();
|
||||
final RenderEditable editable = RenderEditable(
|
||||
backgroundCursorColor: Colors.grey,
|
||||
|
@ -425,9 +425,6 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
||||
/// actual current wall-clock time.
|
||||
Clock get clock;
|
||||
|
||||
@override
|
||||
SamplingClock? get debugSamplingClock => _TestSamplingClock(clock);
|
||||
|
||||
/// Triggers a frame sequence (build/layout/paint/etc),
|
||||
/// then flushes microtasks.
|
||||
///
|
||||
@ -2152,18 +2149,6 @@ class TestViewConfiguration extends ViewConfiguration {
|
||||
String toString() => 'TestViewConfiguration';
|
||||
}
|
||||
|
||||
class _TestSamplingClock implements SamplingClock {
|
||||
_TestSamplingClock(this._clock);
|
||||
|
||||
@override
|
||||
DateTime now() => _clock.now();
|
||||
|
||||
@override
|
||||
Stopwatch stopwatch() => _clock.stopwatch();
|
||||
|
||||
final Clock _clock;
|
||||
}
|
||||
|
||||
const int _kPointerDecay = -2;
|
||||
|
||||
class _LiveTestPointerRecord {
|
||||
|
Loading…
x
Reference in New Issue
Block a user