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
57f097b5
Unverified
Commit
57f097b5
authored
Jan 10, 2022
by
Ian Hickson
Committed by
GitHub
Jan 10, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor devicelab bin/run.dart and other cleanup (#96320)
parent
1c0eade9
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
466 additions
and
352 deletions
+466
-352
run.dart
dev/devicelab/bin/run.dart
+227
-219
framework.dart
dev/devicelab/lib/framework/framework.dart
+31
-25
runner.dart
dev/devicelab/lib/framework/runner.dart
+28
-9
running_processes.dart
dev/devicelab/lib/framework/running_processes.dart
+42
-49
utils.dart
dev/devicelab/lib/framework/utils.dart
+32
-27
perf_tests.dart
dev/devicelab/lib/tasks/perf_tests.dart
+8
-5
run_test.dart
dev/devicelab/test/run_test.dart
+11
-1
runner_test.dart
dev/devicelab/test/runner_test.dart
+2
-3
running_processes_test.dart
dev/devicelab/test/running_processes_test.dart
+82
-10
build_test_task_test.dart
dev/devicelab/test/tasks/build_test_task_test.dart
+1
-2
utils_test.dart
dev/devicelab/test/utils_test.dart
+2
-2
No files found.
dev/devicelab/bin/run.dart
View file @
57f097b5
This diff is collapsed.
Click to expand it.
dev/devicelab/lib/framework/framework.dart
View file @
57f097b5
...
...
@@ -10,6 +10,7 @@ import 'dart:isolate';
import
'package:logging/logging.dart'
;
import
'package:path/path.dart'
as
path
;
import
'package:process/process.dart'
;
import
'package:stack_trace/stack_trace.dart'
;
import
'devices.dart'
;
...
...
@@ -41,35 +42,43 @@ bool _isTaskRegistered = false;
///
/// It is OK for a [task] to perform many things. However, only one task can be
/// registered per Dart VM.
Future
<
TaskResult
>
task
(
TaskFunction
task
)
async
{
///
/// If no `processManager` is provided, a default [LocalProcessManager] is created
/// for the task.
Future
<
TaskResult
>
task
(
TaskFunction
task
,
{
ProcessManager
?
processManager
})
async
{
if
(
_isTaskRegistered
)
throw
StateError
(
'A task is already registered'
);
_isTaskRegistered
=
true
;
processManager
??=
const
LocalProcessManager
();
// TODO(ianh): allow overriding logging.
Logger
.
root
.
level
=
Level
.
ALL
;
Logger
.
root
.
onRecord
.
listen
((
LogRecord
rec
)
{
print
(
'
${rec.level.name}
:
${rec.time}
:
${rec.message}
'
);
});
final
_TaskRunner
runner
=
_TaskRunner
(
task
);
final
_TaskRunner
runner
=
_TaskRunner
(
task
,
processManager
);
runner
.
keepVmAliveUntilTaskRunRequested
();
return
runner
.
whenDone
;
}
class
_TaskRunner
{
_TaskRunner
(
this
.
task
)
{
_TaskRunner
(
this
.
task
,
this
.
processManager
)
{
registerExtension
(
'ext.cocoonRunTask'
,
(
String
method
,
Map
<
String
,
String
>
parameters
)
async
{
final
Duration
?
taskTimeout
=
parameters
.
containsKey
(
'timeoutInMinutes'
)
?
Duration
(
minutes:
int
.
parse
(
parameters
[
'timeoutInMinutes'
]!))
:
null
;
// This is only expected to be passed in unit test runs so they do not
// kill the Dart process that is running them and waste time running config.
final
bool
runFlutterConfig
=
parameters
[
'runFlutterConfig'
]
!=
'false'
;
final
bool
runFlutterConfig
=
parameters
[
'runFlutterConfig'
]
!=
'false'
;
// used by tests to avoid changing the configuration
final
bool
runProcessCleanup
=
parameters
[
'runProcessCleanup'
]
!=
'false'
;
final
TaskResult
result
=
await
run
(
taskTimeout
,
runProcessCleanup:
runProcessCleanup
,
runFlutterConfig:
runFlutterConfig
);
final
String
?
localEngine
=
parameters
[
'localEngine'
];
final
TaskResult
result
=
await
run
(
taskTimeout
,
runProcessCleanup:
runProcessCleanup
,
runFlutterConfig:
runFlutterConfig
,
localEngine:
localEngine
,
);
return
ServiceExtensionResponse
.
result
(
json
.
encode
(
result
.
toJson
()));
});
registerExtension
(
'ext.cocoonRunnerReady'
,
...
...
@@ -79,6 +88,7 @@ class _TaskRunner {
}
final
TaskFunction
task
;
final
ProcessManager
processManager
;
Future
<
Device
?>
_getWorkingDeviceIfAvailable
()
async
{
try
{
...
...
@@ -103,6 +113,7 @@ class _TaskRunner {
Future
<
TaskResult
>
run
(
Duration
?
taskTimeout
,
{
bool
runFlutterConfig
=
true
,
bool
runProcessCleanup
=
true
,
required
String
?
localEngine
,
})
async
{
try
{
_taskStarted
=
true
;
...
...
@@ -113,20 +124,19 @@ class _TaskRunner {
section
(
'Checking running Dart
$exe
processes'
);
beforeRunningDartInstances
=
await
getRunningProcesses
(
processName:
'dart
$exe
'
,
).
toSet
();
final
Set
<
RunningProcessInfo
>
allProcesses
=
await
getRunningProcesses
().
toSet
();
processManager:
processManager
,
);
final
Set
<
RunningProcessInfo
>
allProcesses
=
await
getRunningProcesses
(
processManager:
processManager
);
beforeRunningDartInstances
.
forEach
(
print
);
for
(
final
RunningProcessInfo
info
in
allProcesses
)
{
if
(
info
.
commandLine
.
contains
(
'iproxy'
))
{
print
(
'[LEAK]:
${info.commandLine}
${info.creationDate}
${info.pid}
'
);
}
}
}
else
{
section
(
'Skipping check running Dart
$exe
processes'
);
}
if
(
runFlutterConfig
)
{
print
(
'
e
nabling configs for macOS, Linux, Windows, and Web...'
);
print
(
'
E
nabling configs for macOS, Linux, Windows, and Web...'
);
final
int
configResult
=
await
exec
(
path
.
join
(
flutterDirectory
.
path
,
'bin'
,
'flutter'
),
<
String
>[
'config'
,
'-v'
,
...
...
@@ -134,13 +144,11 @@ class _TaskRunner {
'--enable-windows-desktop'
,
'--enable-linux-desktop'
,
'--enable-web'
,
if
(
localEngine
!=
null
)
...<
String
>[
'--local-engine'
,
localEngine
!
],
if
(
localEngine
!=
null
)
...<
String
>[
'--local-engine'
,
localEngine
],
],
canFail:
true
);
if
(
configResult
!=
0
)
{
print
(
'Failed to enable configuration, tasks may not run.'
);
}
}
else
{
print
(
'Skipping enabling configs for macOS, Linux, Windows, and Web'
);
}
final
Device
?
device
=
await
_getWorkingDeviceIfAvailable
();
...
...
@@ -169,26 +177,24 @@ class _TaskRunner {
}
if
(
runProcessCleanup
)
{
section
(
'
Checking runn
ing Dart
$exe
processes after task...'
);
final
Lis
t
<
RunningProcessInfo
>
afterRunningDartInstances
=
await
getRunningProcesses
(
section
(
'
Terminating linger
ing Dart
$exe
processes after task...'
);
final
Se
t
<
RunningProcessInfo
>
afterRunningDartInstances
=
await
getRunningProcesses
(
processName:
'dart
$exe
'
,
).
toList
();
processManager:
processManager
,
);
for
(
final
RunningProcessInfo
info
in
afterRunningDartInstances
)
{
if
(!
beforeRunningDartInstances
.
contains
(
info
))
{
print
(
'
$info
was leaked by this test.'
);
if
(
result
is
TaskResultCheckProcesses
)
{
result
=
TaskResult
.
failure
(
'This test leaked dart processes'
);
}
final
bool
killed
=
await
killProcess
(
info
.
pid
);
if
(!
killed
)
{
print
(
'Failed to kill process
${info.pid}
.'
);
}
else
{
if
(
await
info
.
terminate
(
processManager:
processManager
))
{
print
(
'Killed process id
${info.pid}
.'
);
}
else
{
print
(
'Failed to kill process
${info.pid}
.'
);
}
}
}
}
else
{
print
(
'Skipping check running Dart
$exe
processes after task'
);
}
_completer
.
complete
(
result
);
return
result
;
...
...
dev/devicelab/lib/framework/runner.dart
View file @
57f097b5
...
...
@@ -4,7 +4,6 @@
import
'dart:async'
;
import
'dart:convert'
;
// import 'dart:core' as core;
import
'dart:io'
;
import
'package:meta/meta.dart'
;
...
...
@@ -29,6 +28,10 @@ import 'utils.dart';
Future
<
void
>
runTasks
(
List
<
String
>
taskNames
,
{
bool
exitOnFirstTestFailure
=
false
,
// terminateStrayDartProcesses defaults to false so that tests don't have to specify it.
// It is set based on the --terminate-stray-dart-processes command line argument in
// normal execution, and that flag defaults to true.
bool
terminateStrayDartProcesses
=
false
,
bool
silent
=
false
,
String
?
deviceId
,
String
?
gitBranch
,
...
...
@@ -50,6 +53,7 @@ Future<void> runTasks(
deviceId:
deviceId
,
localEngine:
localEngine
,
localEngineSrcPath:
localEngineSrcPath
,
terminateStrayDartProcesses:
terminateStrayDartProcesses
,
silent:
silent
,
taskArgs:
taskArgs
,
resultsPath:
resultsPath
,
...
...
@@ -58,15 +62,17 @@ Future<void> runTasks(
isolateParams:
isolateParams
,
);
section
(
'Flaky status for "
$taskName
"'
);
if
(!
result
.
succeeded
)
{
retry
++
;
retry
+=
1
;
}
else
{
section
(
'Flaky status for "
$taskName
"'
);
if
(
retry
>
0
)
{
print
(
'Total
${retry+1}
executions:
$retry
failures and 1
success
'
);
print
(
'Total
${retry+1}
executions:
$retry
failures and 1
false positive.
'
);
print
(
'flaky: true'
);
// TODO(ianh): stop ignoring this failure. We should set exitCode=1, and quit
// if exitOnFirstTestFailure is true.
}
else
{
print
(
'T
otal
${retry+1}
executions: 1 success
'
);
print
(
'T
est passed on first attempt.
'
);
print
(
'flaky: false'
);
}
break
;
...
...
@@ -74,7 +80,8 @@ Future<void> runTasks(
}
if
(!
result
.
succeeded
)
{
print
(
'Total
$retry
executions: 0 success'
);
section
(
'Flaky status for "
$taskName
"'
);
print
(
'Consistently failed across all
$retry
executions.'
);
print
(
'flaky: false'
);
exitCode
=
1
;
if
(
exitOnFirstTestFailure
)
{
...
...
@@ -92,6 +99,7 @@ Future<TaskResult> rerunTask(
String
?
deviceId
,
String
?
localEngine
,
String
?
localEngineSrcPath
,
bool
terminateStrayDartProcesses
=
false
,
bool
silent
=
false
,
List
<
String
>?
taskArgs
,
String
?
resultsPath
,
...
...
@@ -105,6 +113,7 @@ Future<TaskResult> rerunTask(
deviceId:
deviceId
,
localEngine:
localEngine
,
localEngineSrcPath:
localEngineSrcPath
,
terminateStrayDartProcesses:
terminateStrayDartProcesses
,
silent:
silent
,
taskArgs:
taskArgs
,
isolateParams:
isolateParams
,
...
...
@@ -138,11 +147,12 @@ Future<TaskResult> rerunTask(
/// [taskArgs] are passed to the task executable for additional configuration.
Future
<
TaskResult
>
runTask
(
String
taskName
,
{
bool
terminateStrayDartProcesses
=
false
,
bool
silent
=
false
,
String
?
localEngine
,
String
?
localEngineSrcPath
,
String
?
deviceId
,
List
<
String
>
?
taskArgs
,
List
<
String
>
?
taskArgs
,
@visibleForTesting
Map
<
String
,
String
>?
isolateParams
,
})
async
{
final
String
taskExecutable
=
'bin/tasks/
$taskName
.dart'
;
...
...
@@ -198,17 +208,26 @@ Future<TaskResult> runTask(
try
{
final
ConnectionResult
result
=
await
_connectToRunnerIsolate
(
await
uri
.
future
);
print
(
'[
$taskName
] Connected to VM server.'
);
isolateParams
=
isolateParams
==
null
?
<
String
,
String
>{}
:
Map
<
String
,
String
>.
of
(
isolateParams
);
isolateParams
[
'runProcessCleanup'
]
=
terminateStrayDartProcesses
.
toString
();
final
Map
<
String
,
dynamic
>
taskResultJson
=
(
await
result
.
vmService
.
callServiceExtension
(
'ext.cocoonRunTask'
,
args:
isolateParams
,
isolateId:
result
.
isolate
.
id
,
)).
json
!;
final
TaskResult
taskResult
=
TaskResult
.
fromJson
(
taskResultJson
);
await
runner
.
exitCode
;
final
int
exitCode
=
await
runner
.
exitCode
;
print
(
'[
$taskName
] Process terminated with exit code
$exitCode
.'
);
return
taskResult
;
}
catch
(
error
,
stack
)
{
print
(
'[
$taskName
] Task runner system failed with exception!
\n
$error
\n
$stack
'
);
rethrow
;
}
finally
{
if
(!
runnerFinished
)
if
(!
runnerFinished
)
{
print
(
'[
$taskName
] Terminating process...'
);
runner
.
kill
(
ProcessSignal
.
sigkill
);
}
await
stdoutSub
.
cancel
();
await
stderrSub
.
cancel
();
}
...
...
dev/devicelab/lib/framework/running_processes.dart
View file @
57f097b5
...
...
@@ -9,12 +9,12 @@ import 'package:process/process.dart';
@immutable
class
RunningProcessInfo
{
const
RunningProcessInfo
(
this
.
pid
,
this
.
c
reationDate
,
this
.
commandLin
e
)
const
RunningProcessInfo
(
this
.
pid
,
this
.
c
ommandLine
,
this
.
creationDat
e
)
:
assert
(
pid
!=
null
),
assert
(
commandLine
!=
null
);
final
int
pid
;
final
String
commandLine
;
final
String
pid
;
final
DateTime
creationDate
;
@override
...
...
@@ -25,57 +25,54 @@ class RunningProcessInfo {
&&
other
.
creationDate
==
creationDate
;
}
Future
<
bool
>
terminate
({
required
ProcessManager
processManager
})
async
{
// This returns true when the signal is sent, not when the process goes away.
// See also https://github.com/dart-lang/sdk/issues/40759 (killPid should wait for process to be terminated).
if
(
Platform
.
isWindows
)
{
// TODO(ianh): Move Windows to killPid once we can.
// - killPid on Windows has not-useful return code: https://github.com/dart-lang/sdk/issues/47675
final
ProcessResult
result
=
await
processManager
.
run
(<
String
>[
'taskkill.exe'
,
'/pid'
,
'
$pid
'
,
'/f'
,
]);
return
result
.
exitCode
==
0
;
}
return
processManager
.
killPid
(
pid
,
ProcessSignal
.
sigkill
);
}
@override
int
get
hashCode
=>
Object
.
hash
(
pid
,
commandLine
,
creationDate
);
@override
String
toString
()
{
return
'RunningProcesses{pid:
$pid
, commandLine:
$commandLine
, creationDate:
$creationDate
}'
;
}
}
Future
<
bool
>
killProcess
(
String
pid
,
{
ProcessManager
?
processManager
})
async
{
assert
(
pid
!=
null
,
'Must specify a pid to kill'
);
processManager
??=
const
LocalProcessManager
();
ProcessResult
result
;
if
(
Platform
.
isWindows
)
{
result
=
await
processManager
.
run
(<
String
>[
'taskkill.exe'
,
'/pid'
,
pid
,
'/f'
,
]);
}
else
{
result
=
await
processManager
.
run
(<
String
>[
'kill'
,
'-9'
,
pid
,
]);
return
'RunningProcesses(pid:
$pid
, commandLine:
$commandLine
, creationDate:
$creationDate
)'
;
}
return
result
.
exitCode
==
0
;
}
Stream
<
RunningProcessInfo
>
getRunningProcesses
({
Future
<
Set
<
RunningProcessInfo
>
>
getRunningProcesses
({
String
?
processName
,
ProcessManager
?
processManager
,
required
ProcessManager
processManager
,
})
{
processManager
??=
const
LocalProcessManager
();
if
(
Platform
.
isWindows
)
{
return
windowsRunningProcesses
(
processName
);
return
windowsRunningProcesses
(
processName
,
processManager
);
}
return
posixRunningProcesses
(
processName
,
processManager
);
}
@visibleForTesting
Stream
<
RunningProcessInfo
>
windowsRunningProcesses
(
String
?
processName
)
async
*
{
// PowerShell script to get the command line arguments and create time of
// a process.
Future
<
Set
<
RunningProcessInfo
>>
windowsRunningProcesses
(
String
?
processName
,
ProcessManager
processManager
,
)
async
{
// PowerShell script to get the command line arguments and create time of a process.
// See: https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-process
final
String
script
=
processName
!=
null
?
'"Get-CimInstance Win32_Process -Filter
\\
"name=
\'
$processName
\'\\
" | Select-Object ProcessId,CreationDate,CommandLine | Format-Table -AutoSize | Out-String -Width 4096"'
:
'"Get-CimInstance Win32_Process | Select-Object ProcessId,CreationDate,CommandLine | Format-Table -AutoSize | Out-String -Width 4096"'
;
//
Unfortunately, there doesn't seem to be a good way to get ProcessManager to
// run this.
//
TODO(ianh): Unfortunately, there doesn't seem to be a good way to get
//
ProcessManager to
run this.
final
ProcessResult
result
=
await
Process
.
run
(
'powershell -command
$script
'
,
<
String
>[],
...
...
@@ -84,11 +81,9 @@ Stream<RunningProcessInfo> windowsRunningProcesses(String? processName) async* {
print
(
'Could not list processes!'
);
print
(
result
.
stderr
);
print
(
result
.
stdout
);
return
;
}
for
(
final
RunningProcessInfo
info
in
processPowershellOutput
(
result
.
stdout
as
String
))
{
yield
info
;
return
<
RunningProcessInfo
>{};
}
return
processPowershellOutput
(
result
.
stdout
as
String
).
toSet
();
}
/// Parses the output of the PowerShell script from [windowsRunningProcesses].
...
...
@@ -149,22 +144,22 @@ Iterable<RunningProcessInfo> processPowershellOutput(String output) sync* {
time
=
'
${hours + 12}${time.substring(2)}
'
;
}
final
String
pid
=
line
.
substring
(
0
,
processIdHeaderSize
).
trim
(
);
final
int
pid
=
int
.
parse
(
line
.
substring
(
0
,
processIdHeaderSize
).
trim
()
);
final
DateTime
creationDate
=
DateTime
.
parse
(
'
$year
-
$month
-
${day}
T
$time
'
);
final
String
commandLine
=
line
.
substring
(
commandLineHeaderStart
).
trim
();
yield
RunningProcessInfo
(
pid
,
c
reationDate
,
commandLin
e
);
yield
RunningProcessInfo
(
pid
,
c
ommandLine
,
creationDat
e
);
}
}
@visibleForTesting
Stream
<
RunningProcessInfo
>
posixRunningProcesses
(
Future
<
Set
<
RunningProcessInfo
>
>
posixRunningProcesses
(
String
?
processName
,
ProcessManager
processManager
,
)
async
*
{
)
async
{
// Cirrus is missing this in Linux for some reason.
if
(!
processManager
.
canRun
(
'ps'
))
{
print
(
'Cannot list processes on this system:
`ps`
not available.'
);
return
;
print
(
'Cannot list processes on this system:
"ps"
not available.'
);
return
<
RunningProcessInfo
>{}
;
}
final
ProcessResult
result
=
await
processManager
.
run
(<
String
>[
'ps'
,
...
...
@@ -175,11 +170,9 @@ Stream<RunningProcessInfo> posixRunningProcesses(
print
(
'Could not list processes!'
);
print
(
result
.
stderr
);
print
(
result
.
stdout
);
return
;
}
for
(
final
RunningProcessInfo
info
in
processPsOutput
(
result
.
stdout
as
String
,
processName
))
{
yield
info
;
return
<
RunningProcessInfo
>{};
}
return
processPsOutput
(
result
.
stdout
as
String
,
processName
).
toSet
();
}
/// Parses the output of the command in [posixRunningProcesses].
...
...
@@ -240,8 +233,8 @@ Iterable<RunningProcessInfo> processPsOutput(
final
DateTime
creationDate
=
DateTime
.
parse
(
'
$year
-
$month
-
${day}
T
$time
'
);
line
=
line
.
substring
(
24
).
trim
();
final
int
nextSpace
=
line
.
indexOf
(
' '
);
final
String
pid
=
line
.
substring
(
0
,
nextSpace
);
final
int
pid
=
int
.
parse
(
line
.
substring
(
0
,
nextSpace
)
);
final
String
commandLine
=
line
.
substring
(
nextSpace
+
1
);
yield
RunningProcessInfo
(
pid
,
c
reationDate
,
commandLin
e
);
yield
RunningProcessInfo
(
pid
,
c
ommandLine
,
creationDat
e
);
}
}
dev/devicelab/lib/framework/utils.dart
View file @
57f097b5
...
...
@@ -20,14 +20,18 @@ import 'task_result.dart';
String
cwd
=
Directory
.
current
.
path
;
/// The local engine to use for [flutter] and [evalFlutter], if any.
String
?
get
localEngine
{
///
/// This is set as an environment variable when running the task, see runTask in runner.dart.
String
?
get
localEngineFromEnv
{
const
bool
isDefined
=
bool
.
hasEnvironment
(
'localEngine'
);
return
isDefined
?
const
String
.
fromEnvironment
(
'localEngine'
)
:
null
;
}
/// The local engine source path to use if a local engine is used for [flutter]
/// and [evalFlutter].
String
?
get
localEngineSrcPath
{
///
/// This is set as an environment variable when running the task, see runTask in runner.dart.
String
?
get
localEngineSrcPathFromEnv
{
const
bool
isDefined
=
bool
.
hasEnvironment
(
'localEngineSrcPath'
);
return
isDefined
?
const
String
.
fromEnvironment
(
'localEngineSrcPath'
)
:
null
;
}
...
...
@@ -45,9 +49,9 @@ class ProcessInfo {
@override
String
toString
()
{
return
'''
command
:
$command
started
:
$startTime
pid
:
${process.pid}
command:
$command
started:
$startTime
pid :
${process.pid}
'''
.
trim
();
}
...
...
@@ -275,7 +279,7 @@ Future<Process> startProcess(
final
Map
<
String
,
String
>
newEnvironment
=
Map
<
String
,
String
>.
from
(
environment
??
<
String
,
String
>{});
newEnvironment
[
'BOT'
]
=
isBot
?
'true'
:
'false'
;
newEnvironment
[
'LANG'
]
=
'en_US.UTF-8'
;
print
(
'
\n
Executing:
$command
in
$finalWorkingDirectory
with environment
$newEnvironment
'
);
print
(
'
Executing "
$command
" in "
$finalWorkingDirectory
"
with environment
$newEnvironment
'
);
final
Process
process
=
await
_processManager
.
start
(
<
String
>[
executable
,
...?
arguments
],
environment:
newEnvironment
,
...
...
@@ -285,7 +289,6 @@ Future<Process> startProcess(
_runningProcesses
.
add
(
processInfo
);
unawaited
(
process
.
exitCode
.
then
<
void
>((
int
exitCode
)
{
print
(
'"
$executable
" exit code:
$exitCode
'
);
_runningProcesses
.
remove
(
processInfo
);
}));
...
...
@@ -303,7 +306,7 @@ Future<void> forceQuitRunningProcesses() async {
for
(
final
ProcessInfo
p
in
_runningProcesses
)
{
print
(
'Force-quitting process:
\n
$p
'
);
if
(!
p
.
process
.
kill
())
{
print
(
'Failed to force quit process'
);
print
(
'Failed to force quit process
.
'
);
}
}
_runningProcesses
.
clear
();
...
...
@@ -349,7 +352,7 @@ Future<int> _execute(
stderr:
stderr
,
printStdout:
printStdout
,
printStderr:
printStderr
,
);
);
final
int
exitCode
=
await
process
.
exitCode
;
if
(
exitCode
!=
0
&&
!
canFail
)
...
...
@@ -373,23 +376,23 @@ Future<void> forwardStandardStreams(
final
Completer
<
void
>
stdoutDone
=
Completer
<
void
>();
final
Completer
<
void
>
stderrDone
=
Completer
<
void
>();
process
.
stdout
.
transform
<
String
>(
utf8
.
decoder
)
.
transform
<
String
>(
const
LineSplitter
())
.
listen
((
String
line
)
{
if
(
printStdout
)
{
print
(
'stdout:
$line
'
);
}
output
?.
writeln
(
line
);
},
onDone:
()
{
stdoutDone
.
complete
();
});
.
transform
<
String
>(
utf8
.
decoder
)
.
transform
<
String
>(
const
LineSplitter
())
.
listen
((
String
line
)
{
if
(
printStdout
)
{
print
(
'stdout:
$line
'
);
}
output
?.
writeln
(
line
);
},
onDone:
()
{
stdoutDone
.
complete
();
});
process
.
stderr
.
transform
<
String
>(
utf8
.
decoder
)
.
transform
<
String
>(
const
LineSplitter
())
.
listen
((
String
line
)
{
if
(
printStderr
)
{
print
(
'stderr:
$line
'
);
}
stderr
?.
writeln
(
line
);
},
onDone:
()
{
stderrDone
.
complete
();
});
.
transform
<
String
>(
utf8
.
decoder
)
.
transform
<
String
>(
const
LineSplitter
())
.
listen
((
String
line
)
{
if
(
printStderr
)
{
print
(
'stderr:
$line
'
);
}
stderr
?.
writeln
(
line
);
},
onDone:
()
{
stderrDone
.
complete
();
});
return
Future
.
wait
<
void
>(<
Future
<
void
>>[
stdoutDone
.
future
,
...
...
@@ -436,6 +439,8 @@ List<String> flutterCommandArgs(String command, List<String> options) {
'run'
,
'screenshot'
,
};
final
String
?
localEngine
=
localEngineFromEnv
;
final
String
?
localEngineSrcPath
=
localEngineSrcPathFromEnv
;
return
<
String
>[
command
,
if
(
deviceOperatingSystem
==
DeviceOperatingSystem
.
ios
&&
supportedDeviceTimeoutCommands
.
contains
(
command
))
...
...
@@ -448,8 +453,8 @@ List<String> flutterCommandArgs(String command, List<String> options) {
'--screenshot'
,
hostAgent
.
dumpDirectory
!.
path
,
],
if
(
localEngine
!=
null
)
...<
String
>[
'--local-engine'
,
localEngine
!
],
if
(
localEngineSrcPath
!=
null
)
...<
String
>[
'--local-engine-src-path'
,
localEngineSrcPath
!
],
if
(
localEngine
!=
null
)
...<
String
>[
'--local-engine'
,
localEngine
],
if
(
localEngineSrcPath
!=
null
)
...<
String
>[
'--local-engine-src-path'
,
localEngineSrcPath
],
...
options
,
];
}
...
...
dev/devicelab/lib/tasks/perf_tests.dart
View file @
57f097b5
...
...
@@ -847,12 +847,14 @@ class PerfTest {
final
Device
device
=
await
devices
.
workingDevice
;
await
device
.
unlock
();
final
String
deviceId
=
device
.
deviceId
;
final
String
?
localEngine
=
localEngineFromEnv
;
final
String
?
localEngineSrcPath
=
localEngineSrcPathFromEnv
;
await
flutter
(
'drive'
,
options:
<
String
>[
if
(
localEngine
!=
null
)
...<
String
>[
'--local-engine'
,
localEngine
!
],
...<
String
>[
'--local-engine'
,
localEngine
],
if
(
localEngineSrcPath
!=
null
)
...<
String
>[
'--local-engine-src-path'
,
localEngineSrcPath
!
],
...<
String
>[
'--local-engine-src-path'
,
localEngineSrcPath
],
'--no-dds'
,
'--no-android-gradle-daemon'
,
'-v'
,
...
...
@@ -1028,15 +1030,16 @@ class PerfTestWithSkSL extends PerfTest {
if
(
File
(
_vmserviceFileName
).
existsSync
())
{
File
(
_vmserviceFileName
).
deleteSync
();
}
final
String
?
localEngine
=
localEngineFromEnv
;
final
String
?
localEngineSrcPath
=
localEngineSrcPathFromEnv
;
_runProcess
=
await
startProcess
(
_flutterPath
,
<
String
>[
'run'
,
if
(
localEngine
!=
null
)
...<
String
>[
'--local-engine'
,
localEngine
!
],
...<
String
>[
'--local-engine'
,
localEngine
],
if
(
localEngineSrcPath
!=
null
)
...<
String
>[
'--local-engine-src-path'
,
localEngineSrcPath
!
],
...<
String
>[
'--local-engine-src-path'
,
localEngineSrcPath
],
'--no-dds'
,
if
(
deviceOperatingSystem
==
DeviceOperatingSystem
.
ios
)
...<
String
>[
...
...
dev/devicelab/test/run_test.dart
View file @
57f097b5
...
...
@@ -4,6 +4,7 @@
import
'dart:io'
;
import
'package:flutter_devicelab/framework/utils.dart'
show
rm
;
import
'package:path/path.dart'
as
path
;
import
'package:process/process.dart'
;
...
...
@@ -20,6 +21,7 @@ void main() {
final
ProcessResult
scriptProcess
=
processManager
.
runSync
(<
String
>[
dart
,
'bin/run.dart'
,
'--no-terminate-stray-dart-processes'
,
...
otherArgs
,
for
(
final
String
testName
in
testNames
)
...<
String
>[
'-t'
,
testName
],
]);
...
...
@@ -87,9 +89,14 @@ void main() {
test
(
'runs A/B test'
,
()
async
{
final
Directory
tempDirectory
=
Directory
.
systemTemp
.
createTempSync
(
'flutter_devicelab_ab_test.'
);
final
File
abResultsFile
=
File
(
path
.
join
(
tempDirectory
.
path
,
'test_results.json'
));
expect
(
abResultsFile
.
existsSync
(),
isFalse
);
final
ProcessResult
result
=
await
runScript
(
<
String
>[
'smoke_test_success'
],
<
String
>[
'--ab=2'
,
'--local-engine=host_debug_unopt'
],
<
String
>[
'--ab=2'
,
'--local-engine=host_debug_unopt'
,
'--ab-result-file'
,
abResultsFile
.
path
],
);
expect
(
result
.
exitCode
,
0
);
...
...
@@ -137,6 +144,9 @@ void main() {
'metric2
\t
123.00 (0.00%)
\t
123.00 (0.00%)
\t
1.00x
\t\n
'
,
),
);
expect
(
abResultsFile
.
existsSync
(),
isTrue
);
rm
(
tempDirectory
,
recursive:
true
);
});
test
(
'fails to upload results to Cocoon if flags given'
,
()
async
{
...
...
dev/devicelab/test/runner_test.dart
View file @
57f097b5
...
...
@@ -11,7 +11,6 @@ import 'common.dart';
void
main
(
)
{
final
Map
<
String
,
String
>
isolateParams
=
<
String
,
String
>{
'runFlutterConfig'
:
'false'
,
'runProcessCleanup'
:
'false'
,
'timeoutInMinutes'
:
'1'
,
};
List
<
String
>
printLog
;
...
...
@@ -27,7 +26,7 @@ void main() {
logs:
printLog
,
);
expect
(
printLog
.
length
,
2
);
expect
(
printLog
[
0
],
'T
otal 1 executions: 1 success
'
);
expect
(
printLog
[
0
],
'T
est passed on first attempt.
'
);
expect
(
printLog
[
1
],
'flaky: false'
);
});
...
...
@@ -40,7 +39,7 @@ void main() {
logs:
printLog
,
);
expect
(
printLog
.
length
,
2
);
expect
(
printLog
[
0
],
'
Total 3 executions: 0 success
'
);
expect
(
printLog
[
0
],
'
Consistently failed across all 3 executions.
'
);
expect
(
printLog
[
1
],
'flaky: false'
);
});
});
...
...
dev/devicelab/test/running_processes_test.dart
View file @
57f097b5
...
...
@@ -2,7 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'package:flutter_devicelab/framework/running_processes.dart'
;
import
'package:process/process.dart'
;
import
'common.dart'
;
void
main
(
)
{
...
...
@@ -24,19 +30,19 @@ ProcessId CreationDate CommandLine
results
,
equals
(<
RunningProcessInfo
>[
RunningProcessInfo
(
'6552'
,
DateTime
(
2019
,
7
,
3
,
17
,
0
,
27
),
6552
,
r'"C:\tools\dart-sdk\bin\dart.exe" .\bin\agent.dart ci'
,
DateTime
(
2019
,
7
,
3
,
17
,
0
,
27
),
),
RunningProcessInfo
(
'6553'
,
DateTime
(
2019
,
7
,
3
,
22
,
0
,
27
),
6553
,
r'"C:\tools\dart-sdk1\bin\dart.exe" .\bin\agent.dart ci'
,
DateTime
(
2019
,
7
,
3
,
22
,
0
,
27
),
),
RunningProcessInfo
(
'6554'
,
DateTime
(
2019
,
7
,
3
,
11
,
0
,
27
),
6554
,
r'"C:\tools\dart-sdk2\bin\dart.exe" .\bin\agent.dart ci'
,
DateTime
(
2019
,
7
,
3
,
11
,
0
,
27
),
),
]));
});
...
...
@@ -55,15 +61,81 @@ Sat Mar 9 20:13:00 2019 49 /usr/sbin/syslogd
results
,
equals
(<
RunningProcessInfo
>[
RunningProcessInfo
(
'1'
,
DateTime
(
2019
,
3
,
9
,
20
,
12
,
47
),
1
,
'/sbin/launchd'
,
DateTime
(
2019
,
3
,
9
,
20
,
12
,
47
),
),
RunningProcessInfo
(
'49'
,
DateTime
(
2019
,
3
,
9
,
20
,
13
),
49
,
'/usr/sbin/syslogd'
,
DateTime
(
2019
,
3
,
9
,
20
,
13
),
),
]));
});
test
(
'RunningProcessInfo.terminate'
,
()
{
final
RunningProcessInfo
process
=
RunningProcessInfo
(
123
,
'test'
,
DateTime
(
456
));
final
FakeProcessManager
fakeProcessManager
=
FakeProcessManager
();
process
.
terminate
(
processManager:
fakeProcessManager
);
if
(
Platform
.
isWindows
)
{
expect
(
fakeProcessManager
.
log
,
<
String
>[
'run([taskkill.exe, /pid, 123, /f], null, null, null, null, null, null)'
]);
}
else
{
expect
(
fakeProcessManager
.
log
,
<
String
>[
'killPid(123, SIGKILL)'
]);
}
});
}
class
FakeProcessManager
implements
ProcessManager
{
final
List
<
String
>
log
=
<
String
>[];
@override
bool
canRun
(
Object
?
a
,
{
String
?
workingDirectory
})
{
log
.
add
(
'canRun(
$a
,
$workingDirectory
)'
);
return
true
;
}
@override
bool
killPid
(
int
a
,
[
ProcessSignal
?
b
])
{
log
.
add
(
'killPid(
$a
,
$b
)'
);
return
true
;
}
@override
Future
<
ProcessResult
>
run
(
List
<
Object
>
a
,
{
Map
<
String
,
String
>?
environment
,
bool
?
includeParentEnvironment
,
bool
?
runInShell
,
Encoding
?
stderrEncoding
,
Encoding
?
stdoutEncoding
,
String
?
workingDirectory
,
})
async
{
log
.
add
(
'run(
$a
,
$environment
,
$includeParentEnvironment
,
$runInShell
,
$stderrEncoding
,
$stdoutEncoding
,
$workingDirectory
)'
);
return
ProcessResult
(
1
,
0
,
'stdout'
,
'stderr'
);
}
@override
ProcessResult
runSync
(
List
<
Object
>
a
,
{
Map
<
String
,
String
>?
environment
,
bool
?
includeParentEnvironment
,
bool
?
runInShell
,
Encoding
?
stderrEncoding
,
Encoding
?
stdoutEncoding
,
String
?
workingDirectory
,
})
{
log
.
add
(
'runSync(
$a
,
$environment
,
$includeParentEnvironment
,
$runInShell
,
$stderrEncoding
,
$stdoutEncoding
,
$workingDirectory
)'
);
return
ProcessResult
(
1
,
0
,
'stdout'
,
'stderr'
);
}
@override
Future
<
Process
>
start
(
List
<
Object
>
a
,
{
Map
<
String
,
String
>?
environment
,
bool
?
includeParentEnvironment
,
ProcessStartMode
?
mode
,
bool
?
runInShell
,
String
?
workingDirectory
,
})
{
log
.
add
(
'start(
$a
,
$environment
,
$includeParentEnvironment
,
$mode
,
$runInShell
,
$workingDirectory
)'
);
return
Completer
<
Process
>().
future
;
}
}
dev/devicelab/test/tasks/build_test_task_test.dart
View file @
57f097b5
...
...
@@ -12,7 +12,6 @@ import '../common.dart';
void
main
(
)
{
final
Map
<
String
,
String
>
isolateParams
=
<
String
,
String
>{
'runFlutterConfig'
:
'false'
,
'runProcessCleanup'
:
'false'
,
'timeoutInMinutes'
:
'1'
,
};
...
...
@@ -66,7 +65,7 @@ void main() {
final
String
capturedPrint
=
capturedPrintLines
.
toString
();
expect
(
capturedPrint
,
contains
(
'with environment {FLUTTER_DEVICELAB_DEVICEID: FAKE_SUCCESS, BOT: true, LANG: en_US.UTF-8}'
));
expect
(
capturedPrint
,
contains
(
'
exit code: 0
'
));
expect
(
capturedPrint
,
contains
(
'
Process terminated with exit code 0.
'
));
});
test
(
'throws exception when build and test arg are given'
,
()
async
{
...
...
dev/devicelab/test/utils_test.dart
View file @
57f097b5
...
...
@@ -36,8 +36,8 @@ void main() {
group
(
'engine environment declarations'
,
()
{
test
(
'localEngine'
,
()
{
expect
(
localEngine
,
null
);
expect
(
localEngineSrcPath
,
null
);
expect
(
localEngine
FromEnv
,
null
);
expect
(
localEngineSrcPath
FromEnv
,
null
);
});
});
}
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