Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
186d1e9b
Unverified
Commit
186d1e9b
authored
Dec 09, 2017
by
Ian Hickson
Committed by
GitHub
Dec 09, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Have the framework in charge of scheduling frames. (#13344)
...instead of the engine.
parent
425bd5a8
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
418 additions
and
100 deletions
+418
-100
ticker_expectation.txt
dev/automated_tests/flutter_test/ticker_expectation.txt
+16
-0
ticker_test.dart
dev/automated_tests/flutter_test/ticker_test.dart
+16
-0
binding.dart
packages/flutter/lib/src/rendering/binding.dart
+5
-22
binding.dart
packages/flutter/lib/src/scheduler/binding.dart
+236
-33
ticker.dart
packages/flutter/lib/src/scheduler/ticker.dart
+15
-3
message_codec.dart
packages/flutter/lib/src/services/message_codec.dart
+2
-0
binding.dart
packages/flutter/lib/src/widgets/binding.dart
+10
-26
service_extensions_test.dart
...ages/flutter/test/foundation/service_extensions_test.dart
+13
-0
animation_test.dart
packages/flutter/test/scheduler/animation_test.dart
+2
-1
scheduler_test.dart
packages/flutter/test/scheduler/scheduler_test.dart
+15
-14
ticker_test.dart
packages/flutter/test/scheduler/ticker_test.dart
+23
-1
binding_test.dart
packages/flutter/test/widgets/binding_test.dart
+52
-0
binding.dart
packages/flutter_test/lib/src/binding.dart
+8
-0
test_test.dart
packages/flutter_tools/test/commands/test_test.dart
+5
-0
No files found.
dev/automated_tests/flutter_test/ticker_expectation.txt
0 → 100644
View file @
186d1e9b
[^═]*(this line contains the test framework's output with the clock and so forth)?
══╡ EXCEPTION CAUGHT BY SCHEDULER LIBRARY ╞═════════════════════════════════════════════════════════
The following message was thrown:
An animation is still running even after the widget tree was disposed.
There was one transient callback left. The stack trace for when it was registered is as follows:
── callback 2 ──
<<skip until matching line>>
#[0-9]+ main.+ \(.+/flutter/dev/automated_tests/flutter_test/ticker_test\.dart:[0-9]+:[0-9]+\)
<<skip until matching line>>
════════════════════════════════════════════════════════════════════════════════════════════════════
.*..:.. \+0 -1: - Does flutter_test catch leaking tickers\? \[E\]
Test failed\. See exception logs above\.
The test description was: Does flutter_test catch leaking tickers\?
*
.*..:.. \+0 -1: Some tests failed\. *
dev/automated_tests/flutter_test/ticker_test.dart
0 → 100644
View file @
186d1e9b
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'Does flutter_test catch leaking tickers?'
,
(
WidgetTester
tester
)
async
{
new
Ticker
((
Duration
duration
)
{
})..
start
();
final
ByteData
message
=
const
StringCodec
().
encodeMessage
(
'AppLifecycleState.paused'
);
await
BinaryMessages
.
handlePlatformMessage
(
'flutter/lifecycle'
,
message
,
(
_
)
{});
});
}
packages/flutter/lib/src/rendering/binding.dart
View file @
186d1e9b
...
...
@@ -105,8 +105,8 @@ abstract class RendererBinding extends BindingBase with ServicesBinding, Schedul
);
registerSignalServiceExtension
(
name:
'debugDumpSemanticsTreeInInverseHitTestOrder'
,
callback:
()
{
debugDumpSemanticsTree
(
DebugSemanticsDumpOrder
.
inverseHitTest
);
return
debugPrintDone
;
}
name:
'debugDumpSemanticsTreeInInverseHitTestOrder'
,
callback:
()
{
debugDumpSemanticsTree
(
DebugSemanticsDumpOrder
.
inverseHitTest
);
return
debugPrintDone
;
}
);
}
...
...
@@ -139,14 +139,17 @@ abstract class RendererBinding extends BindingBase with ServicesBinding, Schedul
/// Called when the system metrics change.
///
/// See [Window.onMetricsChanged].
@protected
void
handleMetricsChanged
()
{
assert
(
renderView
!=
null
);
renderView
.
configuration
=
createViewConfiguration
();
scheduleForcedFrame
();
}
/// Called when the platform text scale factor changes.
///
/// See [Window.onTextScaleFactorChanged].
@protected
void
handleTextScaleFactorChanged
()
{
}
/// Returns a [ViewConfiguration] configured for the [RenderView] based on the
...
...
@@ -266,26 +269,6 @@ abstract class RendererBinding extends BindingBase with ServicesBinding, Schedul
pipelineOwner
.
flushSemantics
();
// this also sends the semantics to the OS.
}
/// Schedule a frame to run as soon as possible, rather than waiting for
/// the engine to request a frame.
///
/// This is used during application startup so that the first frame (which is
/// likely to be quite expensive) gets a few extra milliseconds to run.
void
scheduleWarmUpFrame
()
{
// We use timers here to ensure that microtasks flush in between.
//
// We call resetEpoch after this frame so that, in the hot reload case, the
// very next frame pretends to have occurred immediately after this warm-up
// frame. The warm-up frame's timestamp will typically be far in the past
// (the time of the last real frame), so if we didn't reset the epoch we
// would see a sudden jump from the old time in the warm-up frame to the new
// time in the "real" frame. The biggest problem with this is that implicit
// animations end up being triggered at the old time and then skipping every
// frame and finishing in the new time.
Timer
.
run
(()
{
handleBeginFrame
(
null
);
});
Timer
.
run
(()
{
handleDrawFrame
();
resetEpoch
();
});
}
@override
Future
<
Null
>
performReassemble
()
async
{
await
super
.
performReassemble
();
...
...
packages/flutter/lib/src/scheduler/binding.dart
View file @
186d1e9b
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/scheduler/ticker.dart
View file @
186d1e9b
...
...
@@ -101,9 +101,21 @@ class Ticker {
/// A ticker that is [muted] can be active (see [isActive]) yet not be
/// ticking. In that case, the ticker will not call its callback, and
/// [isTicking] will be false, but time will still be progressing.
// TODO(ianh): we should teach the scheduler binding about the lifecycle events
// and then this could return an accurate view of the actual scheduler.
bool
get
isTicking
=>
_future
!=
null
&&
!
muted
;
///
/// This will return false if the [Scheduler.lifecycleState] is one that
/// indicates the application is not currently visible (e.g. if the device's
/// screen is turned off).
bool
get
isTicking
{
if
(
_future
==
null
)
return
false
;
if
(
muted
)
return
false
;
if
(
SchedulerBinding
.
instance
.
framesEnabled
)
return
true
;
if
(
SchedulerBinding
.
instance
.
schedulerPhase
!=
SchedulerPhase
.
idle
)
return
true
;
// for example, we might be in a warm-up frame or forced frame
return
false
;
}
/// Whether time is elapsing for this [Ticker]. Becomes true when [start] is
/// called and false when [stop] is called.
...
...
packages/flutter/lib/src/services/message_codec.dart
View file @
186d1e9b
...
...
@@ -8,6 +8,8 @@ import 'package:flutter/foundation.dart';
import
'platform_channel.dart'
;
export
'dart:typed_data'
show
ByteData
;
/// A message encoding/decoding mechanism.
///
/// Both operations throw an exception, if conversion fails. Such situations
...
...
packages/flutter/lib/src/widgets/binding.dart
View file @
186d1e9b
...
...
@@ -231,7 +231,7 @@ abstract class WidgetsBindingObserver {
}
/// The glue between the widgets layer and the Flutter engine.
abstract
class
WidgetsBinding
extends
BindingBase
with
GestureBinding
,
RendererBinding
{
abstract
class
WidgetsBinding
extends
BindingBase
with
SchedulerBinding
,
GestureBinding
,
RendererBinding
{
// This class is intended to be used as a mixin, and should not be
// extended directly.
factory
WidgetsBinding
.
_
()
=>
null
;
...
...
@@ -243,7 +243,6 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
buildOwner
.
onBuildScheduled
=
_handleBuildScheduled
;
ui
.
window
.
onLocaleChanged
=
handleLocaleChanged
;
SystemChannels
.
navigation
.
setMethodCallHandler
(
_handleNavigationInvocation
);
SystemChannels
.
lifecycle
.
setMessageHandler
(
_handleLifecycleMessage
);
SystemChannels
.
system
.
setMessageHandler
(
_handleSystemMessage
);
}
...
...
@@ -369,6 +368,8 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
/// Calls [dispatchLocaleChanged] to notify the binding observers.
///
/// See [Window.onLocaleChanged].
@protected
@mustCallSuper
void
handleLocaleChanged
()
{
dispatchLocaleChanged
(
ui
.
window
.
locale
);
}
...
...
@@ -379,6 +380,8 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
///
/// This is called by [handleLocaleChanged] when the [Window.onLocaleChanged]
/// notification is received.
@protected
@mustCallSuper
void
dispatchLocaleChanged
(
Locale
locale
)
{
for
(
WidgetsBindingObserver
observer
in
_observers
)
observer
.
didChangeLocale
(
locale
);
...
...
@@ -398,6 +401,7 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
///
/// This method exposes the `popRoute` notification from
/// [SystemChannels.navigation].
@protected
Future
<
Null
>
handlePopRoute
()
async
{
for
(
WidgetsBindingObserver
observer
in
new
List
<
WidgetsBindingObserver
>.
from
(
_observers
))
{
if
(
await
observer
.
didPopRoute
())
...
...
@@ -416,6 +420,8 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
///
/// This method exposes the `pushRoute` notification from
/// [SystemChannels.navigation].
@protected
@mustCallSuper
Future
<
Null
>
handlePushRoute
(
String
route
)
async
{
for
(
WidgetsBindingObserver
observer
in
new
List
<
WidgetsBindingObserver
>.
from
(
_observers
))
{
if
(
await
observer
.
didPushRoute
(
route
))
...
...
@@ -433,35 +439,13 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
return
new
Future
<
Null
>.
value
();
}
/// Called when the application lifecycle state changes.
///
/// Notifies all the observers using
/// [WidgetsBindingObserver.didChangeAppLifecycleState].
///
/// This method exposes notifications from [SystemChannels.lifecycle].
@override
void
handleAppLifecycleStateChanged
(
AppLifecycleState
state
)
{
super
.
handleAppLifecycleStateChanged
(
state
);
for
(
WidgetsBindingObserver
observer
in
_observers
)
observer
.
didChangeAppLifecycleState
(
state
);
}
Future
<
String
>
_handleLifecycleMessage
(
String
message
)
async
{
switch
(
message
)
{
case
'AppLifecycleState.paused'
:
handleAppLifecycleStateChanged
(
AppLifecycleState
.
paused
);
break
;
case
'AppLifecycleState.resumed'
:
handleAppLifecycleStateChanged
(
AppLifecycleState
.
resumed
);
break
;
case
'AppLifecycleState.inactive'
:
handleAppLifecycleStateChanged
(
AppLifecycleState
.
inactive
);
break
;
case
'AppLifecycleState.suspending'
:
handleAppLifecycleStateChanged
(
AppLifecycleState
.
suspending
);
break
;
}
return
null
;
}
/// Called when the operating system notifies the application of a memory
/// pressure situation.
///
...
...
packages/flutter/test/foundation/service_extensions_test.dart
View file @
186d1e9b
...
...
@@ -40,9 +40,11 @@ class TestServiceExtensionsBinding extends BindingBase
}
int
reassembled
=
0
;
bool
pendingReassemble
=
false
;
@override
Future
<
Null
>
performReassemble
()
{
reassembled
+=
1
;
pendingReassemble
=
true
;
return
super
.
performReassemble
();
}
...
...
@@ -60,6 +62,17 @@ class TestServiceExtensionsBinding extends BindingBase
ui
.
window
.
onDrawFrame
();
}
@override
void
scheduleForcedFrame
()
{
expect
(
true
,
isFalse
);
}
@override
void
scheduleWarmUpFrame
()
{
expect
(
pendingReassemble
,
isTrue
);
pendingReassemble
=
false
;
}
Future
<
Null
>
flushMicrotasks
()
{
final
Completer
<
Null
>
completer
=
new
Completer
<
Null
>();
Timer
.
run
(
completer
.
complete
);
...
...
packages/flutter/test/scheduler/animation_test.dart
View file @
186d1e9b
...
...
@@ -4,11 +4,12 @@
import
'package:flutter/foundation.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/services.dart'
;
import
'package:test/test.dart'
;
import
'scheduler_tester.dart'
;
class
TestSchedulerBinding
extends
BindingBase
with
SchedulerBinding
{
}
class
TestSchedulerBinding
extends
BindingBase
with
S
ervicesBinding
,
S
chedulerBinding
{
}
void
main
(
)
{
final
SchedulerBinding
scheduler
=
new
TestSchedulerBinding
();
...
...
packages/flutter/test/scheduler/scheduler_test.dart
View file @
186d1e9b
...
...
@@ -4,9 +4,10 @@
import
'package:flutter/foundation.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/services.dart'
;
import
'package:test/test.dart'
;
class
TestSchedulerBinding
extends
BindingBase
with
SchedulerBinding
{
}
class
TestSchedulerBinding
extends
BindingBase
with
S
ervicesBinding
,
S
chedulerBinding
{
}
class
TestStrategy
{
int
allowedPriority
=
10000
;
...
...
@@ -32,20 +33,20 @@ void main() {
strategy
.
allowedPriority
=
100
;
for
(
int
i
=
0
;
i
<
3
;
i
+=
1
)
scheduler
.
handleEventLoopCallback
(
);
expect
(
scheduler
.
handleEventLoopCallback
(),
isFalse
);
expect
(
executedTasks
.
isEmpty
,
isTrue
);
strategy
.
allowedPriority
=
50
;
for
(
int
i
=
0
;
i
<
3
;
i
+=
1
)
scheduler
.
handleEventLoopCallback
(
);
expect
(
executedTasks
.
length
,
equals
(
1
));
expect
(
scheduler
.
handleEventLoopCallback
(),
i
==
0
?
isTrue
:
isFalse
);
expect
(
executedTasks
,
hasLength
(
1
));
expect
(
executedTasks
.
single
,
equals
(
80
));
executedTasks
.
clear
();
strategy
.
allowedPriority
=
20
;
for
(
int
i
=
0
;
i
<
3
;
i
+=
1
)
scheduler
.
handleEventLoopCallback
(
);
expect
(
executedTasks
.
length
,
equals
(
2
));
expect
(
scheduler
.
handleEventLoopCallback
(),
i
<
2
?
isTrue
:
isFalse
);
expect
(
executedTasks
,
hasLength
(
2
));
expect
(
executedTasks
[
0
],
equals
(
23
));
expect
(
executedTasks
[
1
],
equals
(
23
));
executedTasks
.
clear
();
...
...
@@ -55,32 +56,32 @@ void main() {
scheduleAddingTask
(
5
);
scheduleAddingTask
(
97
);
for
(
int
i
=
0
;
i
<
3
;
i
+=
1
)
scheduler
.
handleEventLoopCallback
(
);
expect
(
executedTasks
.
length
,
equals
(
2
));
expect
(
scheduler
.
handleEventLoopCallback
(),
i
<
2
?
isTrue
:
isFalse
);
expect
(
executedTasks
,
hasLength
(
2
));
expect
(
executedTasks
[
0
],
equals
(
99
));
expect
(
executedTasks
[
1
],
equals
(
97
));
executedTasks
.
clear
();
strategy
.
allowedPriority
=
10
;
for
(
int
i
=
0
;
i
<
3
;
i
+=
1
)
scheduler
.
handleEventLoopCallback
(
);
expect
(
executedTasks
.
length
,
equals
(
2
));
expect
(
scheduler
.
handleEventLoopCallback
(),
i
<
2
?
isTrue
:
isFalse
);
expect
(
executedTasks
,
hasLength
(
2
));
expect
(
executedTasks
[
0
],
equals
(
19
));
expect
(
executedTasks
[
1
],
equals
(
11
));
executedTasks
.
clear
();
strategy
.
allowedPriority
=
1
;
for
(
int
i
=
0
;
i
<
4
;
i
+=
1
)
scheduler
.
handleEventLoopCallback
(
);
expect
(
executedTasks
.
length
,
equals
(
3
));
expect
(
scheduler
.
handleEventLoopCallback
(),
i
<
3
?
isTrue
:
isFalse
);
expect
(
executedTasks
,
hasLength
(
3
));
expect
(
executedTasks
[
0
],
equals
(
5
));
expect
(
executedTasks
[
1
],
equals
(
3
));
expect
(
executedTasks
[
2
],
equals
(
2
));
executedTasks
.
clear
();
strategy
.
allowedPriority
=
0
;
scheduler
.
handleEventLoopCallback
(
);
expect
(
executedTasks
.
length
,
equals
(
1
));
expect
(
scheduler
.
handleEventLoopCallback
(),
isFalse
);
expect
(
executedTasks
,
hasLength
(
1
));
expect
(
executedTasks
[
0
],
equals
(
0
));
});
}
packages/flutter/test/scheduler/ticker_test.dart
View file @
186d1e9b
...
...
@@ -3,13 +3,14 @@
// found in the LICENSE file.
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'Ticker mute control test'
,
(
WidgetTester
tester
)
async
{
int
tickCount
=
0
;
void
handleTick
(
Duration
duration
)
{
++
tickCount
;
tickCount
+=
1
;
}
final
Ticker
ticker
=
new
Ticker
(
handleTick
);
...
...
@@ -81,4 +82,25 @@ void main() {
expect
(
ticker
,
hasOneLineDescription
);
expect
(
ticker
.
toString
(
debugIncludeStack:
true
),
contains
(
'testFunction'
));
});
testWidgets
(
'Ticker stops ticking when application is paused'
,
(
WidgetTester
tester
)
async
{
int
tickCount
=
0
;
void
handleTick
(
Duration
duration
)
{
tickCount
+=
1
;
}
final
Ticker
ticker
=
new
Ticker
(
handleTick
);
ticker
.
start
();
expect
(
ticker
.
isTicking
,
isTrue
);
expect
(
ticker
.
isActive
,
isTrue
);
expect
(
tickCount
,
equals
(
0
));
final
ByteData
message
=
const
StringCodec
().
encodeMessage
(
'AppLifecycleState.paused'
);
await
BinaryMessages
.
handlePlatformMessage
(
'flutter/lifecycle'
,
message
,
(
_
)
{});
expect
(
ticker
.
isTicking
,
isFalse
);
expect
(
ticker
.
isActive
,
isTrue
);
ticker
.
stop
();
});
}
packages/flutter/test/widgets/binding_test.dart
View file @
186d1e9b
...
...
@@ -84,4 +84,56 @@ void main() {
WidgetsBinding
.
instance
.
removeObserver
(
observer
);
});
testWidgets
(
'Application lifecycle affects frame scheduling'
,
(
WidgetTester
tester
)
async
{
ByteData
message
;
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
message
=
const
StringCodec
().
encodeMessage
(
'AppLifecycleState.paused'
);
await
BinaryMessages
.
handlePlatformMessage
(
'flutter/lifecycle'
,
message
,
(
_
)
{});
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
message
=
const
StringCodec
().
encodeMessage
(
'AppLifecycleState.resumed'
);
await
BinaryMessages
.
handlePlatformMessage
(
'flutter/lifecycle'
,
message
,
(
_
)
{});
expect
(
tester
.
binding
.
hasScheduledFrame
,
isTrue
);
await
tester
.
pump
();
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
message
=
const
StringCodec
().
encodeMessage
(
'AppLifecycleState.inactive'
);
await
BinaryMessages
.
handlePlatformMessage
(
'flutter/lifecycle'
,
message
,
(
_
)
{});
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
message
=
const
StringCodec
().
encodeMessage
(
'AppLifecycleState.suspending'
);
await
BinaryMessages
.
handlePlatformMessage
(
'flutter/lifecycle'
,
message
,
(
_
)
{});
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
message
=
const
StringCodec
().
encodeMessage
(
'AppLifecycleState.inactive'
);
await
BinaryMessages
.
handlePlatformMessage
(
'flutter/lifecycle'
,
message
,
(
_
)
{});
expect
(
tester
.
binding
.
hasScheduledFrame
,
isTrue
);
await
tester
.
pump
();
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
message
=
const
StringCodec
().
encodeMessage
(
'AppLifecycleState.paused'
);
await
BinaryMessages
.
handlePlatformMessage
(
'flutter/lifecycle'
,
message
,
(
_
)
{});
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
tester
.
binding
.
scheduleFrame
();
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
tester
.
binding
.
scheduleForcedFrame
();
expect
(
tester
.
binding
.
hasScheduledFrame
,
isTrue
);
await
tester
.
pump
();
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
int
frameCount
=
0
;
tester
.
binding
.
addPostFrameCallback
((
Duration
duration
)
{
frameCount
+=
1
;
});
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
1
));
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
expect
(
frameCount
,
0
);
tester
.
binding
.
scheduleWarmUpFrame
();
// this actually tests flutter_test's implementation
expect
(
tester
.
binding
.
hasScheduledFrame
,
isFalse
);
expect
(
frameCount
,
1
);
});
}
packages/flutter_test/lib/src/binding.dart
View file @
186d1e9b
...
...
@@ -583,6 +583,7 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
handleBeginFrame
(
null
);
_fakeAsync
.
flushMicrotasks
();
handleDrawFrame
();
_fakeAsync
.
flushMicrotasks
();
}
@override
...
...
@@ -829,6 +830,13 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
super
.
scheduleFrame
();
}
@override
void
scheduleForcedFrame
()
{
if
(
framePolicy
==
LiveTestWidgetsFlutterBindingFramePolicy
.
benchmark
)
return
;
// In benchmark mode, don't actually schedule any engine frames.
super
.
scheduleForcedFrame
();
}
bool
_doDrawThisFrame
;
@override
...
...
packages/flutter_tools/test/commands/test_test.dart
View file @
186d1e9b
...
...
@@ -38,6 +38,11 @@ void main() {
return
_testFile
(
'test_async_utils_unguarded'
,
automatedTestsDirectory
,
flutterTestDirectory
);
});
testUsingContext
(
'report a nice error when a Ticker is left running'
,
()
async
{
Cache
.
flutterRoot
=
'../..'
;
return
_testFile
(
'ticker'
,
automatedTestsDirectory
,
flutterTestDirectory
);
});
testUsingContext
(
'report a nice error when a pubspec.yaml is missing a flutter_test dependency'
,
()
async
{
final
String
missingDependencyTests
=
fs
.
path
.
join
(
'..'
,
'..'
,
'dev'
,
'missing_dependency_tests'
);
Cache
.
flutterRoot
=
'../..'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment