Commit 73cd70f7 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Add test coverage for lastElapsedDuration (#4705)

Also, fix the bug where apps would assert when you change the time dilation.
Use that mechanism to fix the animation controller tests.
parent e91f3eef
......@@ -16,7 +16,16 @@ import 'priority.dart';
export 'dart:ui' show VoidCallback;
/// Slows down animations by this factor to help in development.
double timeDilation = 1.0;
double get timeDilation => _timeDilation;
double _timeDilation = 1.0;
set timeDilation(double value) {
if (_timeDilation == value)
return;
// We need to resetEpoch first so that we capture start of the epoch with the
// current time dilation.
SchedulerBinding.instance?.resetEpoch();
_timeDilation = value;
}
/// A frame-related callback from the scheduler.
///
......@@ -368,6 +377,28 @@ abstract class SchedulerBinding extends BindingBase {
_hasScheduledFrame = true;
}
Duration _firstRawTimeStampInEpoch;
Duration _epochStart = Duration.ZERO;
Duration _lastRawTimeStamp = Duration.ZERO;
void resetEpoch() {
_epochStart = _adjustForEpoch(_lastRawTimeStamp);
_firstRawTimeStampInEpoch = null;
}
/// Adjusts the given time stamp into the current epoch.
///
/// This both offsets the time stamp to account for when the epoch started
/// (both in raw time and in the epoch's own time line) and scales the time
/// stamp to reflect the time dilation in the current epoch.
///
/// These mechanisms together combine to ensure that the durations we give
/// during frame callbacks are monotonically increasing.
Duration _adjustForEpoch(Duration rawTimeStamp) {
Duration rawDurationSinceEpoch = _firstRawTimeStampInEpoch == null ? Duration.ZERO : rawTimeStamp - _firstRawTimeStampInEpoch;
return new Duration(microseconds: (rawDurationSinceEpoch.inMicroseconds / timeDilation).round() + _epochStart.inMicroseconds);
}
/// Called by the engine to produce a new frame.
///
/// This function first calls all the callbacks registered by
......@@ -377,11 +408,12 @@ abstract class SchedulerBinding extends BindingBase {
/// callbacks registered by [addPostFrameCallback].
void handleBeginFrame(Duration rawTimeStamp) {
Timeline.startSync('Frame');
_firstRawTimeStampInEpoch ??= rawTimeStamp;
Duration timeStamp = _adjustForEpoch(rawTimeStamp);
_lastRawTimeStamp = rawTimeStamp;
assert(!_isProducingFrame);
_isProducingFrame = true;
_hasScheduledFrame = false;
Duration timeStamp = new Duration(
microseconds: (rawTimeStamp.inMicroseconds / timeDilation).round());
_invokeTransientFrameCallbacks(timeStamp);
for (FrameCallback callback in _persistentCallbacks)
......
......@@ -7,8 +7,12 @@ import 'package:flutter/widgets.dart';
import 'package:test/test.dart';
void main() {
test('Can set value during status callback', () {
setUp(() {
WidgetsFlutterBinding.ensureInitialized();
WidgetsBinding.instance.resetEpoch();
});
test('Can set value during status callback', () {
AnimationController controller = new AnimationController(
duration: const Duration(milliseconds: 100)
);
......@@ -40,7 +44,6 @@ void main() {
});
test('Receives status callbacks for forward and reverse', () {
WidgetsFlutterBinding.ensureInitialized();
AnimationController controller = new AnimationController(
duration: const Duration(milliseconds: 100)
);
......@@ -103,7 +106,6 @@ void main() {
});
test('Forward and reverse from values', () {
WidgetsFlutterBinding.ensureInitialized();
AnimationController controller = new AnimationController(
duration: const Duration(milliseconds: 100)
);
......@@ -131,7 +133,6 @@ void main() {
});
test('Can fling to upper and lower bounds', () {
WidgetsFlutterBinding.ensureInitialized();
AnimationController controller = new AnimationController(
duration: const Duration(milliseconds: 100)
);
......@@ -158,4 +159,16 @@ void main() {
expect(largeRangeController.value, -30.0);
largeRangeController.stop();
});
test('lastElapsedDuration control test', () {
AnimationController controller = new AnimationController(
duration: const Duration(milliseconds: 100)
);
controller.forward();
WidgetsBinding.instance.handleBeginFrame(const Duration(milliseconds: 20));
WidgetsBinding.instance.handleBeginFrame(const Duration(milliseconds: 30));
WidgetsBinding.instance.handleBeginFrame(const Duration(milliseconds: 40));
expect(controller.lastElapsedDuration, equals(const Duration(milliseconds: 20)));
controller.stop();
});
}
......@@ -24,7 +24,7 @@ void main() {
void firstCallback(Duration timeStamp) {
expect(firstCallbackRan, isFalse);
expect(secondCallbackRan, isFalse);
expect(timeStamp.inMilliseconds, equals(16));
expect(timeStamp.inMilliseconds, equals(0));
firstCallbackRan = true;
scheduler.cancelFrameCallbackWithId(secondId);
}
......@@ -32,7 +32,7 @@ void main() {
void secondCallback(Duration timeStamp) {
expect(firstCallbackRan, isTrue);
expect(secondCallbackRan, isFalse);
expect(timeStamp.inMilliseconds, equals(16));
expect(timeStamp.inMilliseconds, equals(0));
secondCallbackRan = true;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment