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
ef5ffd08
Unverified
Commit
ef5ffd08
authored
Jul 13, 2021
by
Darren Austin
Committed by
GitHub
Jul 13, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate devicelab framework code to null safety. (#86325)
(Attempt to reland #85993)
parent
43ed3b6b
Changes
28
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
406 additions
and
470 deletions
+406
-470
test.dart
dev/devicelab/lib/command/test.dart
+9
-11
upload_metrics.dart
dev/devicelab/lib/command/upload_metrics.dart
+2
-4
ab.dart
dev/devicelab/lib/framework/ab.dart
+20
-23
apk_utils.dart
dev/devicelab/lib/framework/apk_utils.dart
+19
-14
browser.dart
dev/devicelab/lib/framework/browser.dart
+61
-66
cocoon.dart
dev/devicelab/lib/framework/cocoon.dart
+24
-31
devices.dart
dev/devicelab/lib/framework/devices.dart
+60
-64
framework.dart
dev/devicelab/lib/framework/framework.dart
+15
-17
ios.dart
dev/devicelab/lib/framework/ios.dart
+5
-14
manifest.dart
dev/devicelab/lib/framework/manifest.dart
+11
-14
runner.dart
dev/devicelab/lib/framework/runner.dart
+20
-22
running_processes.dart
dev/devicelab/lib/framework/running_processes.dart
+9
-11
task_result.dart
dev/devicelab/lib/framework/task_result.dart
+6
-6
utils.dart
dev/devicelab/lib/framework/utils.dart
+44
-47
microbenchmarks.dart
dev/devicelab/lib/microbenchmarks.dart
+0
-2
analysis.dart
dev/devicelab/lib/tasks/analysis.dart
+0
-2
build_test_task.dart
dev/devicelab/lib/tasks/build_test_task.dart
+4
-7
dart_plugin_registry_tests.dart
dev/devicelab/lib/tasks/dart_plugin_registry_tests.dart
+2
-4
gallery.dart
dev/devicelab/lib/tasks/gallery.dart
+4
-6
hot_mode_tests.dart
dev/devicelab/lib/tasks/hot_mode_tests.dart
+9
-11
integration_tests.dart
dev/devicelab/lib/tasks/integration_tests.dart
+0
-2
microbenchmarks.dart
dev/devicelab/lib/tasks/microbenchmarks.dart
+0
-2
new_gallery.dart
dev/devicelab/lib/tasks/new_gallery.dart
+0
-2
perf_tests.dart
dev/devicelab/lib/tasks/perf_tests.dart
+64
-61
platform_channels_benchmarks.dart
dev/devicelab/lib/tasks/platform_channels_benchmarks.dart
+0
-2
plugin_tests.dart
dev/devicelab/lib/tasks/plugin_tests.dart
+6
-8
web_benchmarks.dart
dev/devicelab/lib/tasks/web_benchmarks.dart
+12
-15
web_dev_mode_tests.dart
dev/devicelab/lib/tasks/web_dev_mode_tests.dart
+0
-2
No files found.
dev/devicelab/lib/command/test.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'package:args/command_runner.dart'
;
import
'package:args/command_runner.dart'
;
import
'package:flutter_devicelab/framework/runner.dart'
;
import
'package:flutter_devicelab/framework/runner.dart'
;
...
@@ -64,19 +62,19 @@ class TestCommand extends Command<void> {
...
@@ -64,19 +62,19 @@ class TestCommand extends Command<void> {
@override
@override
Future
<
void
>
run
()
async
{
Future
<
void
>
run
()
async
{
final
List
<
String
>
taskArgsRaw
=
argResults
[
'task-args'
]
as
List
<
String
>;
final
List
<
String
>
taskArgsRaw
=
argResults
!
[
'task-args'
]
as
List
<
String
>;
// Prepend '--' to convert args to options when passed to task
// Prepend '--' to convert args to options when passed to task
final
List
<
String
>
taskArgs
=
taskArgsRaw
.
map
((
String
taskArg
)
=>
'--
$taskArg
'
).
toList
();
final
List
<
String
>
taskArgs
=
taskArgsRaw
.
map
((
String
taskArg
)
=>
'--
$taskArg
'
).
toList
();
print
(
taskArgs
);
print
(
taskArgs
);
await
runTasks
(
await
runTasks
(
<
String
>[
argResults
[
'task'
]
as
String
],
<
String
>[
argResults
!
[
'task'
]
as
String
],
deviceId:
argResults
[
'device-id'
]
as
String
,
deviceId:
argResults
![
'device-id'
]
as
String
?
,
gitBranch:
argResults
[
'git-branch'
]
as
String
,
gitBranch:
argResults
![
'git-branch'
]
as
String
?
,
localEngine:
argResults
[
'local-engine'
]
as
String
,
localEngine:
argResults
![
'local-engine'
]
as
String
?
,
localEngineSrcPath:
argResults
[
'local-engine-src-path'
]
as
String
,
localEngineSrcPath:
argResults
![
'local-engine-src-path'
]
as
String
?
,
luciBuilder:
argResults
[
'luci-builder'
]
as
String
,
luciBuilder:
argResults
![
'luci-builder'
]
as
String
?
,
resultsPath:
argResults
[
'results-file'
]
as
String
,
resultsPath:
argResults
![
'results-file'
]
as
String
?
,
silent:
argResults
[
'silent'
]
as
bool
,
silent:
(
argResults
![
'silent'
]
as
bool
?)
??
false
,
taskArgs:
taskArgs
,
taskArgs:
taskArgs
,
);
);
}
}
...
...
dev/devicelab/lib/command/upload_metrics.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'package:args/command_runner.dart'
;
import
'package:args/command_runner.dart'
;
import
'../framework/cocoon.dart'
;
import
'../framework/cocoon.dart'
;
...
@@ -25,8 +23,8 @@ class UploadMetricsCommand extends Command<void> {
...
@@ -25,8 +23,8 @@ class UploadMetricsCommand extends Command<void> {
@override
@override
Future
<
void
>
run
()
async
{
Future
<
void
>
run
()
async
{
final
String
resultsPath
=
argResults
[
'results-file'
]
as
String
;
final
String
resultsPath
=
argResults
!
[
'results-file'
]
as
String
;
final
String
serviceAccountTokenFile
=
argResults
[
'service-account-token-file'
]
as
String
;
final
String
?
serviceAccountTokenFile
=
argResults
![
'service-account-token-file'
]
as
String
?
;
final
Cocoon
cocoon
=
Cocoon
(
serviceAccountTokenPath:
serviceAccountTokenFile
);
final
Cocoon
cocoon
=
Cocoon
(
serviceAccountTokenPath:
serviceAccountTokenFile
);
return
cocoon
.
sendResultsPath
(
resultsPath
);
return
cocoon
.
sendResultsPath
(
resultsPath
);
...
...
dev/devicelab/lib/framework/ab.dart
View file @
ef5ffd08
...
@@ -2,10 +2,7 @@
...
@@ -2,10 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:math'
as
math
;
import
'dart:math'
as
math
;
import
'package:meta/meta.dart'
;
import
'task_result.dart'
;
import
'task_result.dart'
;
...
@@ -43,8 +40,8 @@ class ABTest {
...
@@ -43,8 +40,8 @@ class ABTest {
final
String
localEngine
;
final
String
localEngine
;
final
String
taskName
;
final
String
taskName
;
final
DateTime
runStart
;
final
DateTime
runStart
;
DateTime
_runEnd
;
DateTime
?
_runEnd
;
DateTime
get
runEnd
=>
_runEnd
;
DateTime
?
get
runEnd
=>
_runEnd
;
final
Map
<
String
,
List
<
double
>>
_aResults
;
final
Map
<
String
,
List
<
double
>>
_aResults
;
final
Map
<
String
,
List
<
double
>>
_bResults
;
final
Map
<
String
,
List
<
double
>>
_bResults
;
...
@@ -91,15 +88,15 @@ class ABTest {
...
@@ -91,15 +88,15 @@ class ABTest {
kLocalEngineKeyName:
localEngine
,
kLocalEngineKeyName:
localEngine
,
kTaskNameKeyName:
taskName
,
kTaskNameKeyName:
taskName
,
kRunStartKeyName:
runStart
.
toIso8601String
(),
kRunStartKeyName:
runStart
.
toIso8601String
(),
kRunEndKeyName:
runEnd
.
toIso8601String
(),
kRunEndKeyName:
runEnd
!
.
toIso8601String
(),
kAResultsKeyName:
_aResults
,
kAResultsKeyName:
_aResults
,
kBResultsKeyName:
_bResults
,
kBResultsKeyName:
_bResults
,
};
};
static
void
updateColumnLengths
(
List
<
int
>
lengths
,
List
<
String
>
results
)
{
static
void
updateColumnLengths
(
List
<
int
>
lengths
,
List
<
String
?
>
results
)
{
for
(
int
column
=
0
;
column
<
lengths
.
length
;
column
++)
{
for
(
int
column
=
0
;
column
<
lengths
.
length
;
column
++)
{
if
(
results
[
column
]
!=
null
)
{
if
(
results
[
column
]
!=
null
)
{
lengths
[
column
]
=
math
.
max
(
lengths
[
column
],
results
[
column
]
.
length
);
lengths
[
column
]
=
math
.
max
(
lengths
[
column
],
results
[
column
]
?.
length
??
0
);
}
}
}
}
}
}
...
@@ -107,10 +104,10 @@ class ABTest {
...
@@ -107,10 +104,10 @@ class ABTest {
static
void
formatResult
(
StringBuffer
buffer
,
static
void
formatResult
(
StringBuffer
buffer
,
List
<
int
>
lengths
,
List
<
int
>
lengths
,
List
<
FieldJustification
>
aligns
,
List
<
FieldJustification
>
aligns
,
List
<
String
>
values
)
{
List
<
String
?
>
values
)
{
for
(
int
column
=
0
;
column
<
lengths
.
length
;
column
++)
{
for
(
int
column
=
0
;
column
<
lengths
.
length
;
column
++)
{
final
int
len
=
lengths
[
column
];
final
int
len
=
lengths
[
column
];
String
value
=
values
[
column
];
String
?
value
=
values
[
column
];
if
(
value
==
null
)
{
if
(
value
==
null
)
{
value
=
''
.
padRight
(
len
);
value
=
''
.
padRight
(
len
);
}
else
{
}
else
{
...
@@ -142,9 +139,9 @@ class ABTest {
...
@@ -142,9 +139,9 @@ class ABTest {
final
Map
<
String
,
_ScoreSummary
>
summariesA
=
_summarize
(
_aResults
);
final
Map
<
String
,
_ScoreSummary
>
summariesA
=
_summarize
(
_aResults
);
final
Map
<
String
,
_ScoreSummary
>
summariesB
=
_summarize
(
_bResults
);
final
Map
<
String
,
_ScoreSummary
>
summariesB
=
_summarize
(
_bResults
);
final
List
<
List
<
String
>>
tableRows
=
<
List
<
String
>>[
final
List
<
List
<
String
?>>
tableRows
=
<
List
<
String
?
>>[
for
(
final
String
scoreKey
in
<
String
>{...
summariesA
.
keys
,
...
summariesB
.
keys
})
for
(
final
String
scoreKey
in
<
String
>{...
summariesA
.
keys
,
...
summariesB
.
keys
})
<
String
>[
<
String
?
>[
scoreKey
,
scoreKey
,
summariesA
[
scoreKey
]?.
averageString
,
summariesA
[
scoreKey
]?.
noiseString
,
summariesA
[
scoreKey
]?.
averageString
,
summariesA
[
scoreKey
]?.
noiseString
,
summariesB
[
scoreKey
]?.
averageString
,
summariesB
[
scoreKey
]?.
noiseString
,
summariesB
[
scoreKey
]?.
averageString
,
summariesB
[
scoreKey
]?.
noiseString
,
...
@@ -167,7 +164,7 @@ class ABTest {
...
@@ -167,7 +164,7 @@ class ABTest {
final
List
<
int
>
lengths
=
List
<
int
>.
filled
(
6
,
0
);
final
List
<
int
>
lengths
=
List
<
int
>.
filled
(
6
,
0
);
updateColumnLengths
(
lengths
,
titles
);
updateColumnLengths
(
lengths
,
titles
);
for
(
final
List
<
String
>
row
in
tableRows
)
{
for
(
final
List
<
String
?
>
row
in
tableRows
)
{
updateColumnLengths
(
lengths
,
row
);
updateColumnLengths
(
lengths
,
row
);
}
}
...
@@ -177,7 +174,7 @@ class ABTest {
...
@@ -177,7 +174,7 @@ class ABTest {
FieldJustification
.
CENTER
,
FieldJustification
.
CENTER
,
...
alignments
.
skip
(
1
),
...
alignments
.
skip
(
1
),
],
titles
);
],
titles
);
for
(
final
List
<
String
>
row
in
tableRows
)
{
for
(
final
List
<
String
?
>
row
in
tableRows
)
{
formatResult
(
buffer
,
lengths
,
alignments
,
row
);
formatResult
(
buffer
,
lengths
,
alignments
,
row
);
}
}
...
@@ -192,7 +189,7 @@ class ABTest {
...
@@ -192,7 +189,7 @@ class ABTest {
buffer
.
writeln
(
'
$scoreKey
:'
);
buffer
.
writeln
(
'
$scoreKey
:'
);
buffer
.
write
(
' A:
\t
'
);
buffer
.
write
(
' A:
\t
'
);
if
(
_aResults
.
containsKey
(
scoreKey
))
{
if
(
_aResults
.
containsKey
(
scoreKey
))
{
for
(
final
double
score
in
_aResults
[
scoreKey
])
{
for
(
final
double
score
in
_aResults
[
scoreKey
]
!
)
{
buffer
.
write
(
'
${score.toStringAsFixed(2)}
\t
'
);
buffer
.
write
(
'
${score.toStringAsFixed(2)}
\t
'
);
}
}
}
else
{
}
else
{
...
@@ -202,7 +199,7 @@ class ABTest {
...
@@ -202,7 +199,7 @@ class ABTest {
buffer
.
write
(
' B:
\t
'
);
buffer
.
write
(
' B:
\t
'
);
if
(
_bResults
.
containsKey
(
scoreKey
))
{
if
(
_bResults
.
containsKey
(
scoreKey
))
{
for
(
final
double
score
in
_bResults
[
scoreKey
])
{
for
(
final
double
score
in
_bResults
[
scoreKey
]
!
)
{
buffer
.
write
(
'
${score.toStringAsFixed(2)}
\t
'
);
buffer
.
write
(
'
${score.toStringAsFixed(2)}
\t
'
);
}
}
}
else
{
}
else
{
...
@@ -232,8 +229,8 @@ class ABTest {
...
@@ -232,8 +229,8 @@ class ABTest {
);
);
for
(
final
String
scoreKey
in
_allScoreKeys
)
{
for
(
final
String
scoreKey
in
_allScoreKeys
)
{
final
_ScoreSummary
summaryA
=
summariesA
[
scoreKey
];
final
_ScoreSummary
?
summaryA
=
summariesA
[
scoreKey
];
final
_ScoreSummary
summaryB
=
summariesB
[
scoreKey
];
final
_ScoreSummary
?
summaryB
=
summariesB
[
scoreKey
];
buffer
.
write
(
'
$scoreKey
\t
'
);
buffer
.
write
(
'
$scoreKey
\t
'
);
if
(
summaryA
!=
null
)
{
if
(
summaryA
!=
null
)
{
...
@@ -261,8 +258,8 @@ class ABTest {
...
@@ -261,8 +258,8 @@ class ABTest {
class
_ScoreSummary
{
class
_ScoreSummary
{
_ScoreSummary
({
_ScoreSummary
({
@
required
this
.
average
,
required
this
.
average
,
@
required
this
.
noise
,
required
this
.
noise
,
});
});
/// Average (arithmetic mean) of a series of values collected by a benchmark.
/// Average (arithmetic mean) of a series of values collected by a benchmark.
...
@@ -275,14 +272,14 @@ class _ScoreSummary {
...
@@ -275,14 +272,14 @@ class _ScoreSummary {
String
get
averageString
=>
average
.
toStringAsFixed
(
2
);
String
get
averageString
=>
average
.
toStringAsFixed
(
2
);
String
get
noiseString
=>
'(
${_ratioToPercent(noise)}
)'
;
String
get
noiseString
=>
'(
${_ratioToPercent(noise)}
)'
;
String
improvementOver
(
_ScoreSummary
other
)
{
String
improvementOver
(
_ScoreSummary
?
other
)
{
return
other
==
null
?
''
:
'
${(average / other.average).toStringAsFixed(2)}
x'
;
return
other
==
null
?
''
:
'
${(average / other.average).toStringAsFixed(2)}
x'
;
}
}
}
}
void
_addResult
(
TaskResult
result
,
Map
<
String
,
List
<
double
>>
results
)
{
void
_addResult
(
TaskResult
result
,
Map
<
String
,
List
<
double
>>
results
)
{
for
(
final
String
scoreKey
in
result
.
benchmarkScoreKeys
)
{
for
(
final
String
scoreKey
in
result
.
benchmarkScoreKeys
??
<
String
>[]
)
{
final
double
score
=
(
result
.
data
[
scoreKey
]
as
num
).
toDouble
();
final
double
score
=
(
result
.
data
!
[
scoreKey
]
as
num
).
toDouble
();
results
.
putIfAbsent
(
scoreKey
,
()
=>
<
double
>[]).
add
(
score
);
results
.
putIfAbsent
(
scoreKey
,
()
=>
<
double
>[]).
add
(
score
);
}
}
}
}
...
...
dev/devicelab/lib/framework/apk_utils.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
;
import
'dart:io'
;
import
'package:path/path.dart'
as
path
;
import
'package:path/path.dart'
as
path
;
...
@@ -106,7 +104,7 @@ bool hasMultipleOccurrences(String text, Pattern pattern) {
...
@@ -106,7 +104,7 @@ bool hasMultipleOccurrences(String text, Pattern pattern) {
/// The Android home directory.
/// The Android home directory.
String
get
_androidHome
{
String
get
_androidHome
{
final
String
androidHome
=
Platform
.
environment
[
'ANDROID_HOME'
]
??
final
String
?
androidHome
=
Platform
.
environment
[
'ANDROID_HOME'
]
??
Platform
.
environment
[
'ANDROID_SDK_ROOT'
];
Platform
.
environment
[
'ANDROID_SDK_ROOT'
];
if
(
androidHome
==
null
||
androidHome
.
isEmpty
)
{
if
(
androidHome
==
null
||
androidHome
.
isEmpty
)
{
throw
Exception
(
'Environment variable `ANDROID_SDK_ROOT` is not set.'
);
throw
Exception
(
'Environment variable `ANDROID_SDK_ROOT` is not set.'
);
...
@@ -118,9 +116,9 @@ String get _androidHome {
...
@@ -118,9 +116,9 @@ String get _androidHome {
Future
<
String
>
_evalApkAnalyzer
(
Future
<
String
>
_evalApkAnalyzer
(
List
<
String
>
args
,
{
List
<
String
>
args
,
{
bool
printStdout
=
false
,
bool
printStdout
=
false
,
String
workingDirectory
,
String
?
workingDirectory
,
})
async
{
})
async
{
final
String
javaHome
=
await
findJavaHome
();
final
String
?
javaHome
=
await
findJavaHome
();
if
(
javaHome
==
null
||
javaHome
.
isEmpty
)
{
if
(
javaHome
==
null
||
javaHome
.
isEmpty
)
{
throw
Exception
(
'No JAVA_HOME set.'
);
throw
Exception
(
'No JAVA_HOME set.'
);
}
}
...
@@ -259,7 +257,7 @@ class FlutterProject {
...
@@ -259,7 +257,7 @@ class FlutterProject {
String
get
androidPath
=>
path
.
join
(
rootPath
,
'android'
);
String
get
androidPath
=>
path
.
join
(
rootPath
,
'android'
);
String
get
iosPath
=>
path
.
join
(
rootPath
,
'ios'
);
String
get
iosPath
=>
path
.
join
(
rootPath
,
'ios'
);
Future
<
void
>
addCustomBuildType
(
String
name
,
{
String
initWith
})
async
{
Future
<
void
>
addCustomBuildType
(
String
name
,
{
required
String
initWith
})
async
{
final
File
buildScript
=
File
(
final
File
buildScript
=
File
(
path
.
join
(
androidPath
,
'app'
,
'build.gradle'
),
path
.
join
(
androidPath
,
'app'
,
'build.gradle'
),
);
);
...
@@ -276,7 +274,7 @@ android {
...
@@ -276,7 +274,7 @@ android {
'''
);
'''
);
}
}
Future
<
void
>
addGlobalBuildType
(
String
name
,
{
String
initWith
})
async
{
Future
<
void
>
addGlobalBuildType
(
String
name
,
{
required
String
initWith
})
async
{
final
File
buildScript
=
File
(
final
File
buildScript
=
File
(
path
.
join
(
androidPath
,
'build.gradle'
),
path
.
join
(
androidPath
,
'build.gradle'
),
);
);
...
@@ -360,11 +358,11 @@ flutter:
...
@@ -360,11 +358,11 @@ flutter:
pubspec
.
writeAsStringSync
(
newContents
);
pubspec
.
writeAsStringSync
(
newContents
);
}
}
Future
<
void
>
runGradleTask
(
String
task
,
{
List
<
String
>
options
})
async
{
Future
<
void
>
runGradleTask
(
String
task
,
{
List
<
String
>
?
options
})
async
{
return
_runGradleTask
(
workingDirectory:
androidPath
,
task:
task
,
options:
options
);
return
_runGradleTask
(
workingDirectory:
androidPath
,
task:
task
,
options:
options
);
}
}
Future
<
ProcessResult
>
resultOfGradleTask
(
String
task
,
{
List
<
String
>
options
})
{
Future
<
ProcessResult
>
resultOfGradleTask
(
String
task
,
{
List
<
String
>
?
options
})
{
return
_resultOfGradleTask
(
workingDirectory:
androidPath
,
task:
task
,
options:
options
);
return
_resultOfGradleTask
(
workingDirectory:
androidPath
,
task:
task
,
options:
options
);
}
}
...
@@ -416,7 +414,11 @@ class FlutterModuleProject {
...
@@ -416,7 +414,11 @@ class FlutterModuleProject {
String
get
rootPath
=>
path
.
join
(
parent
.
path
,
name
);
String
get
rootPath
=>
path
.
join
(
parent
.
path
,
name
);
}
}
Future
<
void
>
_runGradleTask
({
String
workingDirectory
,
String
task
,
List
<
String
>
options
})
async
{
Future
<
void
>
_runGradleTask
({
required
String
workingDirectory
,
required
String
task
,
List
<
String
>?
options
,
})
async
{
final
ProcessResult
result
=
await
_resultOfGradleTask
(
final
ProcessResult
result
=
await
_resultOfGradleTask
(
workingDirectory:
workingDirectory
,
workingDirectory:
workingDirectory
,
task:
task
,
task:
task
,
...
@@ -431,10 +433,13 @@ Future<void> _runGradleTask({String workingDirectory, String task, List<String>
...
@@ -431,10 +433,13 @@ Future<void> _runGradleTask({String workingDirectory, String task, List<String>
throw
'Gradle exited with error'
;
throw
'Gradle exited with error'
;
}
}
Future
<
ProcessResult
>
_resultOfGradleTask
({
String
workingDirectory
,
String
task
,
Future
<
ProcessResult
>
_resultOfGradleTask
({
List
<
String
>
options
})
async
{
required
String
workingDirectory
,
required
String
task
,
List
<
String
>?
options
,
})
async
{
section
(
'Find Java'
);
section
(
'Find Java'
);
final
String
javaHome
=
await
findJavaHome
();
final
String
?
javaHome
=
await
findJavaHome
();
if
(
javaHome
==
null
)
if
(
javaHome
==
null
)
throw
TaskResult
.
failure
(
'Could not find Java'
);
throw
TaskResult
.
failure
(
'Could not find Java'
);
...
@@ -465,7 +470,7 @@ Future<ProcessResult> _resultOfGradleTask({String workingDirectory, String task,
...
@@ -465,7 +470,7 @@ Future<ProcessResult> _resultOfGradleTask({String workingDirectory, String task,
}
}
/// Returns [null] if target matches [expectedTarget], otherwise returns an error message.
/// Returns [null] if target matches [expectedTarget], otherwise returns an error message.
String
validateSnapshotDependency
(
FlutterProject
project
,
String
expectedTarget
)
{
String
?
validateSnapshotDependency
(
FlutterProject
project
,
String
expectedTarget
)
{
final
File
snapshotBlob
=
File
(
final
File
snapshotBlob
=
File
(
path
.
join
(
project
.
rootPath
,
'build'
,
'app'
,
'intermediates'
,
path
.
join
(
project
.
rootPath
,
'build'
,
'app'
,
'intermediates'
,
'flutter'
,
'debug'
,
'flutter_build.d'
));
'flutter'
,
'debug'
,
'flutter_build.d'
));
...
...
dev/devicelab/lib/framework/browser.dart
View file @
ef5ffd08
...
@@ -2,15 +2,12 @@
...
@@ -2,15 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
show
json
,
utf8
,
LineSplitter
,
JsonEncoder
;
import
'dart:convert'
show
json
,
utf8
,
LineSplitter
,
JsonEncoder
;
import
'dart:io'
as
io
;
import
'dart:io'
as
io
;
import
'dart:math'
as
math
;
import
'dart:math'
as
math
;
import
'package:flutter_devicelab/common.dart'
;
import
'package:flutter_devicelab/common.dart'
;
import
'package:meta/meta.dart'
;
import
'package:path/path.dart'
as
path
;
import
'package:path/path.dart'
as
path
;
import
'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
;
import
'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
;
...
@@ -32,10 +29,10 @@ class ChromeOptions {
...
@@ -32,10 +29,10 @@ class ChromeOptions {
});
});
/// If not null passed as `--user-data-dir`.
/// If not null passed as `--user-data-dir`.
final
String
userDataDirectory
;
final
String
?
userDataDirectory
;
/// If not null launches a Chrome tab at this URL.
/// If not null launches a Chrome tab at this URL.
final
String
url
;
final
String
?
url
;
/// The width of the Chrome window.
/// The width of the Chrome window.
///
///
...
@@ -49,14 +46,14 @@ class ChromeOptions {
...
@@ -49,14 +46,14 @@ class ChromeOptions {
/// Launches code in "headless" mode, which allows running Chrome in
/// Launches code in "headless" mode, which allows running Chrome in
/// environments without a display, such as LUCI and Cirrus.
/// environments without a display, such as LUCI and Cirrus.
final
bool
headless
;
final
bool
?
headless
;
/// The port Chrome will use for its debugging protocol.
/// The port Chrome will use for its debugging protocol.
///
///
/// If null, Chrome is launched without debugging. When running in headless
/// If null, Chrome is launched without debugging. When running in headless
/// mode without a debug port, Chrome quits immediately. For most tests it is
/// mode without a debug port, Chrome quits immediately. For most tests it is
/// typical to set [headless] to true and set a non-null debug port.
/// typical to set [headless] to true and set a non-null debug port.
final
int
debugPort
;
final
int
?
debugPort
;
}
}
/// A function called when the Chrome process encounters an error.
/// A function called when the Chrome process encounters an error.
...
@@ -79,7 +76,7 @@ class Chrome {
...
@@ -79,7 +76,7 @@ class Chrome {
/// The [onError] callback is called with an error message when the Chrome
/// The [onError] callback is called with an error message when the Chrome
/// process encounters an error. In particular, [onError] is called when the
/// process encounters an error. In particular, [onError] is called when the
/// Chrome process exits prematurely, i.e. before [stop] is called.
/// Chrome process exits prematurely, i.e. before [stop] is called.
static
Future
<
Chrome
>
launch
(
ChromeOptions
options
,
{
String
workingDirectory
,
@
required
ChromeErrorCallback
onError
})
async
{
static
Future
<
Chrome
>
launch
(
ChromeOptions
options
,
{
String
?
workingDirectory
,
required
ChromeErrorCallback
onError
})
async
{
if
(!
io
.
Platform
.
isWindows
)
{
if
(!
io
.
Platform
.
isWindows
)
{
final
io
.
ProcessResult
versionResult
=
io
.
Process
.
runSync
(
_findSystemChromeExecutable
(),
const
<
String
>[
'--version'
]);
final
io
.
ProcessResult
versionResult
=
io
.
Process
.
runSync
(
_findSystemChromeExecutable
(),
const
<
String
>[
'--version'
]);
print
(
'Launching
${versionResult.stdout}
'
);
print
(
'Launching
${versionResult.stdout}
'
);
...
@@ -92,10 +89,10 @@ class Chrome {
...
@@ -92,10 +89,10 @@ class Chrome {
if
(
options
.
userDataDirectory
!=
null
)
if
(
options
.
userDataDirectory
!=
null
)
'--user-data-dir=
${options.userDataDirectory}
'
,
'--user-data-dir=
${options.userDataDirectory}
'
,
if
(
options
.
url
!=
null
)
if
(
options
.
url
!=
null
)
options
.
url
,
options
.
url
!
,
if
(
io
.
Platform
.
environment
[
'CHROME_NO_SANDBOX'
]
==
'true'
)
if
(
io
.
Platform
.
environment
[
'CHROME_NO_SANDBOX'
]
==
'true'
)
'--no-sandbox'
,
'--no-sandbox'
,
if
(
options
.
headless
)
if
(
options
.
headless
==
true
)
'--headless'
,
'--headless'
,
if
(
withDebugging
)
if
(
withDebugging
)
'--remote-debugging-port=
${options.debugPort}
'
,
'--remote-debugging-port=
${options.debugPort}
'
,
...
@@ -116,9 +113,9 @@ class Chrome {
...
@@ -116,9 +113,9 @@ class Chrome {
workingDirectory:
workingDirectory
,
workingDirectory:
workingDirectory
,
);
);
WipConnection
debugConnection
;
WipConnection
?
debugConnection
;
if
(
withDebugging
)
{
if
(
withDebugging
)
{
debugConnection
=
await
_connectToChromeDebugPort
(
chromeProcess
,
options
.
debugPort
);
debugConnection
=
await
_connectToChromeDebugPort
(
chromeProcess
,
options
.
debugPort
!
);
}
}
return
Chrome
.
_
(
chromeProcess
,
onError
,
debugConnection
);
return
Chrome
.
_
(
chromeProcess
,
onError
,
debugConnection
);
...
@@ -126,12 +123,12 @@ class Chrome {
...
@@ -126,12 +123,12 @@ class Chrome {
final
io
.
Process
_chromeProcess
;
final
io
.
Process
_chromeProcess
;
final
ChromeErrorCallback
_onError
;
final
ChromeErrorCallback
_onError
;
final
WipConnection
_debugConnection
;
final
WipConnection
?
_debugConnection
;
bool
_isStopped
=
false
;
bool
_isStopped
=
false
;
Completer
<
void
>
_tracingCompleter
;
Completer
<
void
>
?
_tracingCompleter
;
StreamSubscription
<
WipEvent
>
_tracingSubscription
;
StreamSubscription
<
WipEvent
>
?
_tracingSubscription
;
List
<
Map
<
String
,
dynamic
>>
_tracingData
;
List
<
Map
<
String
,
dynamic
>>
?
_tracingData
;
/// Starts recording a performance trace.
/// Starts recording a performance trace.
///
///
...
@@ -151,24 +148,24 @@ class Chrome {
...
@@ -151,24 +148,24 @@ class Chrome {
// Subscribe to tracing events prior to calling "Tracing.start". Otherwise,
// Subscribe to tracing events prior to calling "Tracing.start". Otherwise,
// we'll miss tracing data.
// we'll miss tracing data.
_tracingSubscription
=
_debugConnection
.
onNotification
.
listen
((
WipEvent
event
)
{
_tracingSubscription
=
_debugConnection
?
.
onNotification
.
listen
((
WipEvent
event
)
{
// We receive data as a sequence of "Tracing.dataCollected" followed by
// We receive data as a sequence of "Tracing.dataCollected" followed by
// "Tracing.tracingComplete" at the end. Until "Tracing.tracingComplete"
// "Tracing.tracingComplete" at the end. Until "Tracing.tracingComplete"
// is received, the data may be incomplete.
// is received, the data may be incomplete.
if
(
event
.
method
==
'Tracing.tracingComplete'
)
{
if
(
event
.
method
==
'Tracing.tracingComplete'
)
{
_tracingCompleter
.
complete
();
_tracingCompleter
!
.
complete
();
_tracingSubscription
.
cancel
();
_tracingSubscription
!
.
cancel
();
_tracingSubscription
=
null
;
_tracingSubscription
=
null
;
}
else
if
(
event
.
method
==
'Tracing.dataCollected'
)
{
}
else
if
(
event
.
method
==
'Tracing.dataCollected'
)
{
final
dynamic
value
=
event
.
params
[
'value'
];
final
dynamic
value
=
event
.
params
?
[
'value'
];
if
(
value
is
!
List
)
{
if
(
value
is
!
List
)
{
throw
FormatException
(
'"Tracing.dataCollected" returned malformed data. '
throw
FormatException
(
'"Tracing.dataCollected" returned malformed data. '
'Expected a List but got:
${value.runtimeType}
'
);
'Expected a List but got:
${value.runtimeType}
'
);
}
}
_tracingData
.
addAll
((
event
.
params
[
'value'
]
as
List
<
dynamic
>).
cast
<
Map
<
String
,
dynamic
>>());
_tracingData
?.
addAll
((
event
.
params
?
[
'value'
]
as
List
<
dynamic
>).
cast
<
Map
<
String
,
dynamic
>>());
}
}
});
});
await
_debugConnection
.
sendCommand
(
'Tracing.start'
,
<
String
,
dynamic
>{
await
_debugConnection
?
.
sendCommand
(
'Tracing.start'
,
<
String
,
dynamic
>{
// The choice of categories is as follows:
// The choice of categories is as follows:
//
//
// blink:
// blink:
...
@@ -190,22 +187,23 @@ class Chrome {
...
@@ -190,22 +187,23 @@ class Chrome {
/// Stops a performance tracing session started by [beginRecordingPerformance].
/// Stops a performance tracing session started by [beginRecordingPerformance].
///
///
/// Returns all the collected tracing data unfiltered.
/// Returns all the collected tracing data unfiltered.
Future
<
List
<
Map
<
String
,
dynamic
>>>
endRecordingPerformance
()
async
{
Future
<
List
<
Map
<
String
,
dynamic
>>
?
>
endRecordingPerformance
()
async
{
await
_debugConnection
.
sendCommand
(
'Tracing.end'
);
await
_debugConnection
!
.
sendCommand
(
'Tracing.end'
);
await
_tracingCompleter
.
future
;
await
_tracingCompleter
!
.
future
;
final
List
<
Map
<
String
,
dynamic
>>
data
=
_tracingData
;
final
List
<
Map
<
String
,
dynamic
>>
?
data
=
_tracingData
;
_tracingCompleter
=
null
;
_tracingCompleter
=
null
;
_tracingData
=
null
;
_tracingData
=
null
;
return
data
;
return
data
;
}
}
Future
<
void
>
reloadPage
({
bool
ignoreCache
=
false
})
async
{
Future
<
void
>
reloadPage
({
bool
ignoreCache
=
false
})
async
{
await
_debugConnection
.
page
.
reload
(
ignoreCache:
ignoreCache
);
await
_debugConnection
?
.
page
.
reload
(
ignoreCache:
ignoreCache
);
}
}
/// Stops the Chrome process.
/// Stops the Chrome process.
void
stop
()
{
void
stop
()
{
_isStopped
=
true
;
_isStopped
=
true
;
_tracingSubscription
?.
cancel
();
_chromeProcess
.
kill
();
_chromeProcess
.
kill
();
}
}
}
}
...
@@ -214,7 +212,7 @@ String _findSystemChromeExecutable() {
...
@@ -214,7 +212,7 @@ String _findSystemChromeExecutable() {
// On some environments, such as the Dart HHH tester, Chrome resides in a
// On some environments, such as the Dart HHH tester, Chrome resides in a
// non-standard location and is provided via the following environment
// non-standard location and is provided via the following environment
// variable.
// variable.
final
String
envExecutable
=
io
.
Platform
.
environment
[
'CHROME_EXECUTABLE'
];
final
String
?
envExecutable
=
io
.
Platform
.
environment
[
'CHROME_EXECUTABLE'
];
if
(
envExecutable
!=
null
)
{
if
(
envExecutable
!=
null
)
{
return
envExecutable
;
return
envExecutable
;
}
}
...
@@ -232,15 +230,12 @@ String _findSystemChromeExecutable() {
...
@@ -232,15 +230,12 @@ String _findSystemChromeExecutable() {
return
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
;
return
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
;
}
else
if
(
io
.
Platform
.
isWindows
)
{
}
else
if
(
io
.
Platform
.
isWindows
)
{
const
String
kWindowsExecutable
=
r'Google\Chrome\Application\chrome.exe'
;
const
String
kWindowsExecutable
=
r'Google\Chrome\Application\chrome.exe'
;
final
List
<
String
>
kWindowsPrefixes
=
<
String
>[
final
List
<
String
>
kWindowsPrefixes
=
<
String
?
>[
io
.
Platform
.
environment
[
'LOCALAPPDATA'
],
io
.
Platform
.
environment
[
'LOCALAPPDATA'
],
io
.
Platform
.
environment
[
'PROGRAMFILES'
],
io
.
Platform
.
environment
[
'PROGRAMFILES'
],
io
.
Platform
.
environment
[
'PROGRAMFILES(X86)'
],
io
.
Platform
.
environment
[
'PROGRAMFILES(X86)'
],
];
]
.
whereType
<
String
>().
toList
()
;
final
String
windowsPrefix
=
kWindowsPrefixes
.
firstWhere
((
String
prefix
)
{
final
String
windowsPrefix
=
kWindowsPrefixes
.
firstWhere
((
String
prefix
)
{
if
(
prefix
==
null
)
{
return
false
;
}
final
String
expectedPath
=
path
.
join
(
prefix
,
kWindowsExecutable
);
final
String
expectedPath
=
path
.
join
(
prefix
,
kWindowsExecutable
);
return
io
.
File
(
expectedPath
).
existsSync
();
return
io
.
File
(
expectedPath
).
existsSync
();
},
orElse:
()
=>
'.'
);
},
orElse:
()
=>
'.'
);
...
@@ -269,7 +264,7 @@ Future<Uri> _getRemoteDebuggerUrl(Uri base) async {
...
@@ -269,7 +264,7 @@ Future<Uri> _getRemoteDebuggerUrl(Uri base) async {
final
io
.
HttpClient
client
=
io
.
HttpClient
();
final
io
.
HttpClient
client
=
io
.
HttpClient
();
final
io
.
HttpClientRequest
request
=
await
client
.
getUrl
(
base
.
resolve
(
'/json/list'
));
final
io
.
HttpClientRequest
request
=
await
client
.
getUrl
(
base
.
resolve
(
'/json/list'
));
final
io
.
HttpClientResponse
response
=
await
request
.
close
();
final
io
.
HttpClientResponse
response
=
await
request
.
close
();
final
List
<
dynamic
>
jsonObject
=
await
json
.
fuse
(
utf8
).
decoder
.
bind
(
response
).
single
as
List
<
dynamic
>
;
final
List
<
dynamic
>
?
jsonObject
=
await
json
.
fuse
(
utf8
).
decoder
.
bind
(
response
).
single
as
List
<
dynamic
>?
;
if
(
jsonObject
==
null
||
jsonObject
.
isEmpty
)
{
if
(
jsonObject
==
null
||
jsonObject
.
isEmpty
)
{
return
base
;
return
base
;
}
}
...
@@ -279,17 +274,17 @@ Future<Uri> _getRemoteDebuggerUrl(Uri base) async {
...
@@ -279,17 +274,17 @@ Future<Uri> _getRemoteDebuggerUrl(Uri base) async {
/// Summarizes a Blink trace down to a few interesting values.
/// Summarizes a Blink trace down to a few interesting values.
class
BlinkTraceSummary
{
class
BlinkTraceSummary
{
BlinkTraceSummary
.
_
({
BlinkTraceSummary
.
_
({
@
required
this
.
averageBeginFrameTime
,
required
this
.
averageBeginFrameTime
,
@
required
this
.
averageUpdateLifecyclePhasesTime
,
required
this
.
averageUpdateLifecyclePhasesTime
,
})
:
averageTotalUIFrameTime
=
averageBeginFrameTime
+
averageUpdateLifecyclePhasesTime
;
})
:
averageTotalUIFrameTime
=
averageBeginFrameTime
+
averageUpdateLifecyclePhasesTime
;
static
BlinkTraceSummary
fromJson
(
List
<
Map
<
String
,
dynamic
>>
traceJson
)
{
static
BlinkTraceSummary
?
fromJson
(
List
<
Map
<
String
,
dynamic
>>
traceJson
)
{
try
{
try
{
// Convert raw JSON data to BlinkTraceEvent objects sorted by timestamp.
// Convert raw JSON data to BlinkTraceEvent objects sorted by timestamp.
List
<
BlinkTraceEvent
>
events
=
traceJson
List
<
BlinkTraceEvent
>
events
=
traceJson
.
map
<
BlinkTraceEvent
>(
BlinkTraceEvent
.
fromJson
)
.
map
<
BlinkTraceEvent
>(
BlinkTraceEvent
.
fromJson
)
.
toList
()
.
toList
()
..
sort
((
BlinkTraceEvent
a
,
BlinkTraceEvent
b
)
=>
a
.
ts
-
b
.
ts
);
..
sort
((
BlinkTraceEvent
a
,
BlinkTraceEvent
b
)
=>
a
.
ts
!
-
b
.
ts
!
);
Exception
noMeasuredFramesFound
()
=>
Exception
(
Exception
noMeasuredFramesFound
()
=>
Exception
(
'No measured frames found in benchmark tracing data. This likely '
'No measured frames found in benchmark tracing data. This likely '
...
@@ -316,7 +311,7 @@ class BlinkTraceSummary {
...
@@ -316,7 +311,7 @@ class BlinkTraceSummary {
return
null
;
return
null
;
}
}
final
int
tabPid
=
firstMeasuredFrameEvent
.
pid
;
final
int
tabPid
=
firstMeasuredFrameEvent
.
pid
!
;
// Filter out data from unrelated processes
// Filter out data from unrelated processes
events
=
events
.
where
((
BlinkTraceEvent
element
)
=>
element
.
pid
==
tabPid
).
toList
();
events
=
events
.
where
((
BlinkTraceEvent
element
)
=>
element
.
pid
==
tabPid
).
toList
();
...
@@ -352,8 +347,8 @@ class BlinkTraceSummary {
...
@@ -352,8 +347,8 @@ class BlinkTraceSummary {
// Compute averages and summarize.
// Compute averages and summarize.
return
BlinkTraceSummary
.
_
(
return
BlinkTraceSummary
.
_
(
averageBeginFrameTime:
_computeAverageDuration
(
frames
.
map
((
BlinkFrame
frame
)
=>
frame
.
beginFrame
).
toList
()),
averageBeginFrameTime:
_computeAverageDuration
(
frames
.
map
((
BlinkFrame
frame
)
=>
frame
.
beginFrame
).
whereType
<
BlinkTraceEvent
>().
toList
()),
averageUpdateLifecyclePhasesTime:
_computeAverageDuration
(
frames
.
map
((
BlinkFrame
frame
)
=>
frame
.
updateAllLifecyclePhases
).
toList
()),
averageUpdateLifecyclePhasesTime:
_computeAverageDuration
(
frames
.
map
((
BlinkFrame
frame
)
=>
frame
.
updateAllLifecyclePhases
).
whereType
<
BlinkTraceEvent
>().
toList
()),
);
);
}
catch
(
_
,
__
)
{
}
catch
(
_
,
__
)
{
final
io
.
File
traceFile
=
io
.
File
(
'./chrome-trace.json'
);
final
io
.
File
traceFile
=
io
.
File
(
'./chrome-trace.json'
);
...
@@ -392,16 +387,16 @@ class BlinkTraceSummary {
...
@@ -392,16 +387,16 @@ class BlinkTraceSummary {
/// Contains events pertaining to a single frame in the Blink trace data.
/// Contains events pertaining to a single frame in the Blink trace data.
class
BlinkFrame
{
class
BlinkFrame
{
/// Corresponds to 'WebViewImpl::beginFrame' event.
/// Corresponds to 'WebViewImpl::beginFrame' event.
BlinkTraceEvent
beginFrame
;
BlinkTraceEvent
?
beginFrame
;
/// Corresponds to 'WebViewImpl::updateAllLifecyclePhases' event.
/// Corresponds to 'WebViewImpl::updateAllLifecyclePhases' event.
BlinkTraceEvent
updateAllLifecyclePhases
;
BlinkTraceEvent
?
updateAllLifecyclePhases
;
/// Corresponds to 'measured_frame' begin event.
/// Corresponds to 'measured_frame' begin event.
BlinkTraceEvent
beginMeasuredFrame
;
BlinkTraceEvent
?
beginMeasuredFrame
;
/// Corresponds to 'measured_frame' end event.
/// Corresponds to 'measured_frame' end event.
BlinkTraceEvent
endMeasuredFrame
;
BlinkTraceEvent
?
endMeasuredFrame
;
}
}
/// Takes a list of events that have non-null [BlinkTraceEvent.tdur] computes
/// Takes a list of events that have non-null [BlinkTraceEvent.tdur] computes
...
@@ -414,7 +409,7 @@ Duration _computeAverageDuration(List<BlinkTraceEvent> events) {
...
@@ -414,7 +409,7 @@ Duration _computeAverageDuration(List<BlinkTraceEvent> events) {
if
(
event
.
tdur
==
null
)
{
if
(
event
.
tdur
==
null
)
{
throw
FormatException
(
'Trace event lacks "tdur" field:
$event
'
);
throw
FormatException
(
'Trace event lacks "tdur" field:
$event
'
);
}
}
return
previousValue
+
event
.
tdur
;
return
previousValue
+
event
.
tdur
!
;
});
});
final
int
sampleCount
=
math
.
min
(
events
.
length
,
_kMeasuredSampleCount
);
final
int
sampleCount
=
math
.
min
(
events
.
length
,
_kMeasuredSampleCount
);
return
Duration
(
microseconds:
sum
~/
sampleCount
);
return
Duration
(
microseconds:
sum
~/
sampleCount
);
...
@@ -426,15 +421,15 @@ Duration _computeAverageDuration(List<BlinkTraceEvent> events) {
...
@@ -426,15 +421,15 @@ Duration _computeAverageDuration(List<BlinkTraceEvent> events) {
/// * https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
/// * https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
class
BlinkTraceEvent
{
class
BlinkTraceEvent
{
BlinkTraceEvent
.
_
({
BlinkTraceEvent
.
_
({
@
required
this
.
args
,
required
this
.
args
,
@
required
this
.
cat
,
required
this
.
cat
,
@
required
this
.
name
,
required
this
.
name
,
@
required
this
.
ph
,
required
this
.
ph
,
@required
this
.
pid
,
this
.
pid
,
@required
this
.
tid
,
this
.
tid
,
@required
this
.
ts
,
this
.
ts
,
@required
this
.
tts
,
this
.
tts
,
@required
this
.
tdur
,
this
.
tdur
,
});
});
/// Parses an event from its JSON representation.
/// Parses an event from its JSON representation.
...
@@ -488,19 +483,19 @@ class BlinkTraceEvent {
...
@@ -488,19 +483,19 @@ class BlinkTraceEvent {
final
String
ph
;
final
String
ph
;
/// Process ID of the process that emitted the event.
/// Process ID of the process that emitted the event.
final
int
pid
;
final
int
?
pid
;
/// Thread ID of the thread that emitted the event.
/// Thread ID of the thread that emitted the event.
final
int
tid
;
final
int
?
tid
;
/// Timestamp in microseconds using tracer clock.
/// Timestamp in microseconds using tracer clock.
final
int
ts
;
final
int
?
ts
;
/// Timestamp in microseconds using thread clock.
/// Timestamp in microseconds using thread clock.
final
int
tts
;
final
int
?
tts
;
/// Event duration in microseconds.
/// Event duration in microseconds.
final
int
tdur
;
final
int
?
tdur
;
/// A "begin frame" event contains all of the scripting time of an animation
/// A "begin frame" event contains all of the scripting time of an animation
/// frame (JavaScript, WebAssembly), plus a negligible amount of internal
/// frame (JavaScript, WebAssembly), plus a negligible amount of internal
...
@@ -556,8 +551,8 @@ class BlinkTraceEvent {
...
@@ -556,8 +551,8 @@ class BlinkTraceEvent {
/// validation and conversion is needed.
/// validation and conversion is needed.
///
///
/// Returns null if the value is null.
/// Returns null if the value is null.
int
_readInt
(
Map
<
String
,
dynamic
>
json
,
String
key
)
{
int
?
_readInt
(
Map
<
String
,
dynamic
>
json
,
String
key
)
{
final
num
jsonValue
=
json
[
key
]
as
num
;
final
num
?
jsonValue
=
json
[
key
]
as
num
?
;
if
(
jsonValue
==
null
)
{
if
(
jsonValue
==
null
)
{
return
null
;
return
null
;
...
@@ -578,10 +573,10 @@ int _readInt(Map<String, dynamic> json, String key) {
...
@@ -578,10 +573,10 @@ int _readInt(Map<String, dynamic> json, String key) {
/// Inconsistency detected by ld.so: ../elf/dl-tls.c: 493: _dl_allocate_tls_init: Assertion `listp->slotinfo[cnt].gen <= GL(dl_tls_generation)' failed!
/// Inconsistency detected by ld.so: ../elf/dl-tls.c: 493: _dl_allocate_tls_init: Assertion `listp->slotinfo[cnt].gen <= GL(dl_tls_generation)' failed!
const
String
_kGlibcError
=
'Inconsistency detected by ld.so'
;
const
String
_kGlibcError
=
'Inconsistency detected by ld.so'
;
Future
<
io
.
Process
>
_spawnChromiumProcess
(
String
executable
,
List
<
String
>
args
,
{
String
workingDirectory
})
async
{
Future
<
io
.
Process
>
_spawnChromiumProcess
(
String
executable
,
List
<
String
>
args
,
{
String
?
workingDirectory
})
async
{
// Keep attempting to launch the browser until one of:
// Keep attempting to launch the browser until one of:
// - Chrome launched successfully, in which case we just return from the loop.
// - Chrome launched successfully, in which case we just return from the loop.
// - The tool detected an unretr
i
able Chrome error, in which case we throw ToolExit.
// - The tool detected an unretr
y
able Chrome error, in which case we throw ToolExit.
while
(
true
)
{
while
(
true
)
{
final
io
.
Process
process
=
await
io
.
Process
.
start
(
executable
,
args
,
workingDirectory:
workingDirectory
);
final
io
.
Process
process
=
await
io
.
Process
.
start
(
executable
,
args
,
workingDirectory:
workingDirectory
);
...
@@ -611,7 +606,7 @@ Future<io.Process> _spawnChromiumProcess(String executable, List<String> args, {
...
@@ -611,7 +606,7 @@ Future<io.Process> _spawnChromiumProcess(String executable, List<String> args, {
'Encountered glibc bug https://sourceware.org/bugzilla/show_bug.cgi?id=19329. '
'Encountered glibc bug https://sourceware.org/bugzilla/show_bug.cgi?id=19329. '
'Will try launching browser again.'
,
'Will try launching browser again.'
,
);
);
return
null
;
return
''
;
}
}
print
(
'Failed to launch browser. Command used to launch it:
${args.join(' ')}
'
);
print
(
'Failed to launch browser. Command used to launch it:
${args.join(' ')}
'
);
throw
Exception
(
throw
Exception
(
...
@@ -630,7 +625,7 @@ Future<io.Process> _spawnChromiumProcess(String executable, List<String> args, {
...
@@ -630,7 +625,7 @@ Future<io.Process> _spawnChromiumProcess(String executable, List<String> args, {
// launching more processes.
// launching more processes.
unawaited
(
process
.
exitCode
.
timeout
(
const
Duration
(
seconds:
1
),
onTimeout:
()
{
unawaited
(
process
.
exitCode
.
timeout
(
const
Duration
(
seconds:
1
),
onTimeout:
()
{
process
.
kill
();
process
.
kill
();
return
null
;
return
0
;
}));
}));
}
}
}
}
dev/devicelab/lib/framework/cocoon.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
show
Encoding
,
json
;
import
'dart:convert'
show
Encoding
,
json
;
import
'dart:io'
;
import
'dart:io'
;
...
@@ -20,12 +18,12 @@ import 'utils.dart';
...
@@ -20,12 +18,12 @@ import 'utils.dart';
typedef
ProcessRunSync
=
ProcessResult
Function
(
typedef
ProcessRunSync
=
ProcessResult
Function
(
String
,
String
,
List
<
String
>,
{
List
<
String
>,
{
Map
<
String
,
String
>
environment
,
Map
<
String
,
String
>
?
environment
,
bool
includeParentEnvironment
,
bool
includeParentEnvironment
,
bool
runInShell
,
bool
runInShell
,
Encoding
stderrEncoding
,
Encoding
?
stderrEncoding
,
Encoding
stdoutEncoding
,
Encoding
?
stdoutEncoding
,
String
workingDirectory
,
String
?
workingDirectory
,
});
});
/// Class for test runner to interact with Flutter's infrastructure service, Cocoon.
/// Class for test runner to interact with Flutter's infrastructure service, Cocoon.
...
@@ -34,8 +32,8 @@ typedef ProcessRunSync = ProcessResult Function(
...
@@ -34,8 +32,8 @@ typedef ProcessRunSync = ProcessResult Function(
/// To retrieve these results, the test runner needs to send results back so the database can be updated.
/// To retrieve these results, the test runner needs to send results back so the database can be updated.
class
Cocoon
{
class
Cocoon
{
Cocoon
({
Cocoon
({
String
serviceAccountTokenPath
,
String
?
serviceAccountTokenPath
,
@visibleForTesting
Client
httpClient
,
@visibleForTesting
Client
?
httpClient
,
@visibleForTesting
this
.
fs
=
const
LocalFileSystem
(),
@visibleForTesting
this
.
fs
=
const
LocalFileSystem
(),
@visibleForTesting
this
.
processRunSync
=
Process
.
runSync
,
@visibleForTesting
this
.
processRunSync
=
Process
.
runSync
,
@visibleForTesting
this
.
requestRetryLimit
=
5
,
@visibleForTesting
this
.
requestRetryLimit
=
5
,
...
@@ -58,7 +56,7 @@ class Cocoon {
...
@@ -58,7 +56,7 @@ class Cocoon {
final
int
requestRetryLimit
;
final
int
requestRetryLimit
;
String
get
commitSha
=>
_commitSha
??
_readCommitSha
();
String
get
commitSha
=>
_commitSha
??
_readCommitSha
();
String
_commitSha
;
String
?
_commitSha
;
/// Parse the local repo for the current running commit.
/// Parse the local repo for the current running commit.
String
_readCommitSha
()
{
String
_readCommitSha
()
{
...
@@ -85,9 +83,9 @@ class Cocoon {
...
@@ -85,9 +83,9 @@ class Cocoon {
/// Send [TaskResult] to Cocoon.
/// Send [TaskResult] to Cocoon.
// TODO(chillers): Remove when sendResultsPath is used in prod. https://github.com/flutter/flutter/issues/72457
// TODO(chillers): Remove when sendResultsPath is used in prod. https://github.com/flutter/flutter/issues/72457
Future
<
void
>
sendTaskResult
({
Future
<
void
>
sendTaskResult
({
@
required
String
builderName
,
required
String
builderName
,
@
required
TaskResult
result
,
required
TaskResult
result
,
@
required
String
gitBranch
,
required
String
gitBranch
,
})
async
{
})
async
{
assert
(
builderName
!=
null
);
assert
(
builderName
!=
null
);
assert
(
gitBranch
!=
null
);
assert
(
gitBranch
!=
null
);
...
@@ -109,16 +107,11 @@ class Cocoon {
...
@@ -109,16 +107,11 @@ class Cocoon {
/// Write the given parameters into an update task request and store the JSON in [resultsPath].
/// Write the given parameters into an update task request and store the JSON in [resultsPath].
Future
<
void
>
writeTaskResultToFile
({
Future
<
void
>
writeTaskResultToFile
({
@required
String
builderName
,
String
?
builderName
,
@required
String
gitBranch
,
String
?
gitBranch
,
@
required
TaskResult
result
,
required
TaskResult
result
,
@
required
String
resultsPath
,
required
String
resultsPath
,
})
async
{
})
async
{
assert
(
builderName
!=
null
);
assert
(
gitBranch
!=
null
);
assert
(
result
!=
null
);
assert
(
resultsPath
!=
null
);
final
Map
<
String
,
dynamic
>
updateRequest
=
_constructUpdateRequest
(
final
Map
<
String
,
dynamic
>
updateRequest
=
_constructUpdateRequest
(
gitBranch:
gitBranch
,
gitBranch:
gitBranch
,
builderName:
builderName
,
builderName:
builderName
,
...
@@ -134,9 +127,9 @@ class Cocoon {
...
@@ -134,9 +127,9 @@ class Cocoon {
}
}
Map
<
String
,
dynamic
>
_constructUpdateRequest
({
Map
<
String
,
dynamic
>
_constructUpdateRequest
({
@required
String
builderName
,
String
?
builderName
,
@
required
TaskResult
result
,
required
TaskResult
result
,
@required
String
gitBranch
,
String
?
gitBranch
,
})
{
})
{
final
Map
<
String
,
dynamic
>
updateRequest
=
<
String
,
dynamic
>{
final
Map
<
String
,
dynamic
>
updateRequest
=
<
String
,
dynamic
>{
'CommitBranch'
:
gitBranch
,
'CommitBranch'
:
gitBranch
,
...
@@ -151,12 +144,12 @@ class Cocoon {
...
@@ -151,12 +144,12 @@ class Cocoon {
final
List
<
String
>
validScoreKeys
=
<
String
>[];
final
List
<
String
>
validScoreKeys
=
<
String
>[];
if
(
result
.
benchmarkScoreKeys
!=
null
)
{
if
(
result
.
benchmarkScoreKeys
!=
null
)
{
for
(
final
String
scoreKey
in
result
.
benchmarkScoreKeys
)
{
for
(
final
String
scoreKey
in
result
.
benchmarkScoreKeys
!
)
{
final
Object
score
=
result
.
data
[
scoreKey
]
;
final
Object
score
=
result
.
data
![
scoreKey
]
as
Object
;
if
(
score
is
num
)
{
if
(
score
is
num
)
{
// Convert all metrics to double, which provide plenty of precision
// Convert all metrics to double, which provide plenty of precision
// without having to add support for multiple numeric types in Cocoon.
// without having to add support for multiple numeric types in Cocoon.
result
.
data
[
scoreKey
]
=
score
.
toDouble
();
result
.
data
!
[
scoreKey
]
=
score
.
toDouble
();
validScoreKeys
.
add
(
scoreKey
);
validScoreKeys
.
add
(
scoreKey
);
}
}
}
}
...
@@ -195,15 +188,15 @@ class Cocoon {
...
@@ -195,15 +188,15 @@ class Cocoon {
class
AuthenticatedCocoonClient
extends
BaseClient
{
class
AuthenticatedCocoonClient
extends
BaseClient
{
AuthenticatedCocoonClient
(
AuthenticatedCocoonClient
(
this
.
_serviceAccountTokenPath
,
{
this
.
_serviceAccountTokenPath
,
{
@visibleForTesting
Client
httpClient
,
@visibleForTesting
Client
?
httpClient
,
@visibleForTesting
FileSystem
filesystem
,
@visibleForTesting
FileSystem
?
filesystem
,
})
:
_delegate
=
httpClient
??
Client
(),
})
:
_delegate
=
httpClient
??
Client
(),
_fs
=
filesystem
??
const
LocalFileSystem
();
_fs
=
filesystem
??
const
LocalFileSystem
();
/// Authentication token to have the ability to upload and record test results.
/// Authentication token to have the ability to upload and record test results.
///
///
/// This is intended to only be passed on automated runs on LUCI post-submit.
/// This is intended to only be passed on automated runs on LUCI post-submit.
final
String
_serviceAccountTokenPath
;
final
String
?
_serviceAccountTokenPath
;
/// Underlying [HttpClient] to send requests to.
/// Underlying [HttpClient] to send requests to.
final
Client
_delegate
;
final
Client
_delegate
;
...
@@ -213,7 +206,7 @@ class AuthenticatedCocoonClient extends BaseClient {
...
@@ -213,7 +206,7 @@ class AuthenticatedCocoonClient extends BaseClient {
/// Value contained in the service account token file that can be used in http requests.
/// Value contained in the service account token file that can be used in http requests.
String
get
serviceAccountToken
=>
_serviceAccountToken
??
_readServiceAccountTokenFile
();
String
get
serviceAccountToken
=>
_serviceAccountToken
??
_readServiceAccountTokenFile
();
String
_serviceAccountToken
;
String
?
_serviceAccountToken
;
/// Get [serviceAccountToken] from the given service account file.
/// Get [serviceAccountToken] from the given service account file.
String
_readServiceAccountTokenFile
()
{
String
_readServiceAccountTokenFile
()
{
...
...
dev/devicelab/lib/framework/devices.dart
View file @
ef5ffd08
...
@@ -2,15 +2,12 @@
...
@@ -2,15 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:io'
;
import
'dart:math'
as
math
;
import
'dart:math'
as
math
;
import
'package:flutter_devicelab/common.dart'
;
import
'package:flutter_devicelab/common.dart'
;
import
'package:meta/meta.dart'
;
import
'package:path/path.dart'
as
path
;
import
'package:path/path.dart'
as
path
;
import
'utils.dart'
;
import
'utils.dart'
;
...
@@ -37,8 +34,8 @@ String getArtifactPath() {
...
@@ -37,8 +34,8 @@ String getArtifactPath() {
}
}
/// Return the item is in idList if find a match, otherwise return null
/// Return the item is in idList if find a match, otherwise return null
String
_findMatchId
(
List
<
String
>
idList
,
String
idPattern
)
{
String
?
_findMatchId
(
List
<
String
>
idList
,
String
idPattern
)
{
String
candidate
;
String
?
candidate
;
idPattern
=
idPattern
.
toLowerCase
();
idPattern
=
idPattern
.
toLowerCase
();
for
(
final
String
id
in
idList
)
{
for
(
final
String
id
in
idList
)
{
if
(
id
.
toLowerCase
()
==
idPattern
)
{
if
(
id
.
toLowerCase
()
==
idPattern
)
{
...
@@ -184,47 +181,46 @@ enum AndroidCPU {
...
@@ -184,47 +181,46 @@ enum AndroidCPU {
}
}
class
AndroidDeviceDiscovery
implements
DeviceDiscovery
{
class
AndroidDeviceDiscovery
implements
DeviceDiscovery
{
factory
AndroidDeviceDiscovery
({
AndroidCPU
cpu
})
{
factory
AndroidDeviceDiscovery
({
AndroidCPU
?
cpu
})
{
return
_instance
??=
AndroidDeviceDiscovery
.
_
(
cpu
);
return
_instance
??=
AndroidDeviceDiscovery
.
_
(
cpu
);
}
}
AndroidDeviceDiscovery
.
_
(
this
.
cpu
);
AndroidDeviceDiscovery
.
_
(
this
.
cpu
);
final
AndroidCPU
cpu
;
final
AndroidCPU
?
cpu
;
// Parses information about a device. Example:
// Parses information about a device. Example:
//
//
// 015d172c98400a03 device usb:340787200X product:nakasi model:Nexus_7 device:grouper
// 015d172c98400a03 device usb:340787200X product:nakasi model:Nexus_7 device:grouper
static
final
RegExp
_kDeviceRegex
=
RegExp
(
r'^(\S+)\s+(\S+)(.*)'
);
static
final
RegExp
_kDeviceRegex
=
RegExp
(
r'^(\S+)\s+(\S+)(.*)'
);
static
AndroidDeviceDiscovery
_instance
;
static
AndroidDeviceDiscovery
?
_instance
;
AndroidDevice
_workingDevice
;
AndroidDevice
?
_workingDevice
;
@override
@override
Future
<
AndroidDevice
>
get
workingDevice
async
{
Future
<
AndroidDevice
>
get
workingDevice
async
{
if
(
_workingDevice
==
null
)
{
if
(
_workingDevice
==
null
)
{
if
(
Platform
.
environment
.
containsKey
(
DeviceIdEnvName
))
{
if
(
Platform
.
environment
.
containsKey
(
DeviceIdEnvName
))
{
final
String
deviceId
=
Platform
.
environment
[
DeviceIdEnvName
];
final
String
deviceId
=
Platform
.
environment
[
DeviceIdEnvName
]
!
;
await
chooseWorkingDeviceById
(
deviceId
);
await
chooseWorkingDeviceById
(
deviceId
);
return
_workingDevice
;
return
_workingDevice
!
;
}
}
await
chooseWorkingDevice
();
await
chooseWorkingDevice
();
}
}
return
_workingDevice
;
return
_workingDevice
!
;
}
}
Future
<
bool
>
_matchesCPURequirement
(
AndroidDevice
device
)
async
{
Future
<
bool
>
_matchesCPURequirement
(
AndroidDevice
device
)
async
{
if
(
cpu
==
null
)
return
true
;
switch
(
cpu
)
{
switch
(
cpu
)
{
case
null
:
return
true
;
case
AndroidCPU
.
arm64
:
case
AndroidCPU
.
arm64
:
return
device
.
isArm64
();
return
device
.
isArm64
();
case
AndroidCPU
.
arm
:
case
AndroidCPU
.
arm
:
return
device
.
isArm
();
return
device
.
isArm
();
}
}
return
true
;
}
}
/// Picks a random Android device out of connected devices and sets it as
/// Picks a random Android device out of connected devices and sets it as
...
@@ -259,11 +255,11 @@ class AndroidDeviceDiscovery implements DeviceDiscovery {
...
@@ -259,11 +255,11 @@ class AndroidDeviceDiscovery implements DeviceDiscovery {
@override
@override
Future
<
void
>
chooseWorkingDeviceById
(
String
deviceId
)
async
{
Future
<
void
>
chooseWorkingDeviceById
(
String
deviceId
)
async
{
final
String
matchedId
=
_findMatchId
(
await
discoverDevices
(),
deviceId
);
final
String
?
matchedId
=
_findMatchId
(
await
discoverDevices
(),
deviceId
);
if
(
matchedId
!=
null
)
{
if
(
matchedId
!=
null
)
{
_workingDevice
=
AndroidDevice
(
deviceId:
matchedId
);
_workingDevice
=
AndroidDevice
(
deviceId:
matchedId
);
if
(
cpu
!=
null
)
{
if
(
cpu
!=
null
)
{
if
(!
await
_matchesCPURequirement
(
_workingDevice
))
{
if
(!
await
_matchesCPURequirement
(
_workingDevice
!
))
{
throw
DeviceException
(
'The selected device
$matchedId
does not match the cpu requirement'
);
throw
DeviceException
(
'The selected device
$matchedId
does not match the cpu requirement'
);
}
}
}
}
...
@@ -290,10 +286,10 @@ class AndroidDeviceDiscovery implements DeviceDiscovery {
...
@@ -290,10 +286,10 @@ class AndroidDeviceDiscovery implements DeviceDiscovery {
continue
;
continue
;
if
(
_kDeviceRegex
.
hasMatch
(
line
))
{
if
(
_kDeviceRegex
.
hasMatch
(
line
))
{
final
Match
match
=
_kDeviceRegex
.
firstMatch
(
line
);
final
Match
match
=
_kDeviceRegex
.
firstMatch
(
line
)
!
;
final
String
deviceID
=
match
[
1
];
final
String
deviceID
=
match
[
1
]
!
;
final
String
deviceState
=
match
[
2
];
final
String
deviceState
=
match
[
2
]
!
;
if
(!
const
<
String
>[
'unauthorized'
,
'offline'
].
contains
(
deviceState
))
{
if
(!
const
<
String
>[
'unauthorized'
,
'offline'
].
contains
(
deviceState
))
{
results
.
add
(
deviceID
);
results
.
add
(
deviceID
);
...
@@ -342,9 +338,9 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
...
@@ -342,9 +338,9 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
FuchsiaDeviceDiscovery
.
_
();
FuchsiaDeviceDiscovery
.
_
();
static
FuchsiaDeviceDiscovery
_instance
;
static
FuchsiaDeviceDiscovery
?
_instance
;
FuchsiaDevice
_workingDevice
;
FuchsiaDevice
?
_workingDevice
;
String
get
_ffx
{
String
get
_ffx
{
final
String
ffx
=
path
.
join
(
getArtifactPath
(),
'fuchsia'
,
'tools'
,
'x64'
,
'ffx'
);
final
String
ffx
=
path
.
join
(
getArtifactPath
(),
'fuchsia'
,
'tools'
,
'x64'
,
'ffx'
);
...
@@ -358,13 +354,13 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
...
@@ -358,13 +354,13 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
Future
<
FuchsiaDevice
>
get
workingDevice
async
{
Future
<
FuchsiaDevice
>
get
workingDevice
async
{
if
(
_workingDevice
==
null
)
{
if
(
_workingDevice
==
null
)
{
if
(
Platform
.
environment
.
containsKey
(
DeviceIdEnvName
))
{
if
(
Platform
.
environment
.
containsKey
(
DeviceIdEnvName
))
{
final
String
deviceId
=
Platform
.
environment
[
DeviceIdEnvName
];
final
String
deviceId
=
Platform
.
environment
[
DeviceIdEnvName
]
!
;
await
chooseWorkingDeviceById
(
deviceId
);
await
chooseWorkingDeviceById
(
deviceId
);
return
_workingDevice
;
return
_workingDevice
!
;
}
}
await
chooseWorkingDevice
();
await
chooseWorkingDevice
();
}
}
return
_workingDevice
;
return
_workingDevice
!
;
}
}
/// Picks the first connected Fuchsia device.
/// Picks the first connected Fuchsia device.
...
@@ -383,8 +379,8 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
...
@@ -383,8 +379,8 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
@override
@override
Future
<
void
>
chooseWorkingDeviceById
(
String
deviceId
)
async
{
Future
<
void
>
chooseWorkingDeviceById
(
String
deviceId
)
async
{
final
String
matchedId
=
_findMatchId
(
await
discoverDevices
(),
deviceId
);
final
String
?
matchedId
=
_findMatchId
(
await
discoverDevices
(),
deviceId
);
if
(
device
Id
!=
null
)
{
if
(
matched
Id
!=
null
)
{
_workingDevice
=
FuchsiaDevice
(
deviceId:
matchedId
);
_workingDevice
=
FuchsiaDevice
(
deviceId:
matchedId
);
print
(
'Choose device by ID:
$matchedId
'
);
print
(
'Choose device by ID:
$matchedId
'
);
return
;
return
;
...
@@ -442,7 +438,7 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
...
@@ -442,7 +438,7 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
}
}
class
AndroidDevice
extends
Device
{
class
AndroidDevice
extends
Device
{
AndroidDevice
({
@
required
this
.
deviceId
})
{
AndroidDevice
({
required
this
.
deviceId
})
{
_updateDeviceInfo
();
_updateDeviceInfo
();
}
}
...
@@ -540,19 +536,19 @@ class AndroidDevice extends Device {
...
@@ -540,19 +536,19 @@ class AndroidDevice extends Device {
}
}
/// Executes [command] on `adb shell` and returns its exit code.
/// Executes [command] on `adb shell` and returns its exit code.
Future
<
void
>
shellExec
(
String
command
,
List
<
String
>
arguments
,
{
Map
<
String
,
String
>
environment
,
bool
silent
=
false
})
async
{
Future
<
void
>
shellExec
(
String
command
,
List
<
String
>
arguments
,
{
Map
<
String
,
String
>
?
environment
,
bool
silent
=
false
})
async
{
await
adb
(<
String
>[
'shell'
,
command
,
...
arguments
],
environment:
environment
,
silent:
silent
);
await
adb
(<
String
>[
'shell'
,
command
,
...
arguments
],
environment:
environment
,
silent:
silent
);
}
}
/// Executes [command] on `adb shell` and returns its standard output as a [String].
/// Executes [command] on `adb shell` and returns its standard output as a [String].
Future
<
String
>
shellEval
(
String
command
,
List
<
String
>
arguments
,
{
Map
<
String
,
String
>
environment
,
bool
silent
=
false
})
{
Future
<
String
>
shellEval
(
String
command
,
List
<
String
>
arguments
,
{
Map
<
String
,
String
>
?
environment
,
bool
silent
=
false
})
{
return
adb
(<
String
>[
'shell'
,
command
,
...
arguments
],
environment:
environment
,
silent:
silent
);
return
adb
(<
String
>[
'shell'
,
command
,
...
arguments
],
environment:
environment
,
silent:
silent
);
}
}
/// Runs `adb` with the given [arguments], selecting this device.
/// Runs `adb` with the given [arguments], selecting this device.
Future
<
String
>
adb
(
Future
<
String
>
adb
(
List
<
String
>
arguments
,
{
List
<
String
>
arguments
,
{
Map
<
String
,
String
>
environment
,
Map
<
String
,
String
>
?
environment
,
bool
silent
=
false
,
bool
silent
=
false
,
})
{
})
{
return
eval
(
return
eval
(
...
@@ -568,18 +564,18 @@ class AndroidDevice extends Device {
...
@@ -568,18 +564,18 @@ class AndroidDevice extends Device {
@override
@override
Future
<
Map
<
String
,
dynamic
>>
getMemoryStats
(
String
packageName
)
async
{
Future
<
Map
<
String
,
dynamic
>>
getMemoryStats
(
String
packageName
)
async
{
final
String
meminfo
=
await
shellEval
(
'dumpsys'
,
<
String
>[
'meminfo'
,
packageName
]);
final
String
meminfo
=
await
shellEval
(
'dumpsys'
,
<
String
>[
'meminfo'
,
packageName
]);
final
Match
match
=
RegExp
(
r'TOTAL\s+(\d+)'
).
firstMatch
(
meminfo
);
final
Match
?
match
=
RegExp
(
r'TOTAL\s+(\d+)'
).
firstMatch
(
meminfo
);
assert
(
match
!=
null
,
'could not parse dumpsys meminfo output'
);
assert
(
match
!=
null
,
'could not parse dumpsys meminfo output'
);
return
<
String
,
dynamic
>{
return
<
String
,
dynamic
>{
'total_kb'
:
int
.
parse
(
match
.
group
(
1
)
),
'total_kb'
:
int
.
parse
(
match
!.
group
(
1
)!
),
};
};
}
}
@override
@override
bool
get
canStreamLogs
=>
true
;
bool
get
canStreamLogs
=>
true
;
bool
_abortedLogging
/*!*/
=
false
;
bool
_abortedLogging
=
false
;
Process
/*?*/
_loggingProcess
;
Process
?
_loggingProcess
;
@override
@override
Future
<
void
>
startLoggingToSink
(
IOSink
sink
,
{
bool
clear
=
true
})
async
{
Future
<
void
>
startLoggingToSink
(
IOSink
sink
,
{
bool
clear
=
true
})
async
{
...
@@ -596,17 +592,17 @@ class AndroidDevice extends Device {
...
@@ -596,17 +592,17 @@ class AndroidDevice extends Device {
// to view the whole log, or just run logcat alongside this.
// to view the whole log, or just run logcat alongside this.
<
String
>[
'-s'
,
deviceId
,
'logcat'
,
'ActivityManager:I'
,
'flutter:V'
,
'*:F'
],
<
String
>[
'-s'
,
deviceId
,
'logcat'
,
'ActivityManager:I'
,
'flutter:V'
,
'*:F'
],
);
);
_loggingProcess
.
stdout
_loggingProcess
!
.
stdout
.
transform
<
String
>(
const
Utf8Decoder
(
allowMalformed:
true
))
.
transform
<
String
>(
const
Utf8Decoder
(
allowMalformed:
true
))
.
listen
((
String
line
)
{
.
listen
((
String
line
)
{
sink
.
write
(
line
);
sink
.
write
(
line
);
});
});
_loggingProcess
.
stderr
_loggingProcess
!
.
stderr
.
transform
<
String
>(
const
Utf8Decoder
(
allowMalformed:
true
))
.
transform
<
String
>(
const
Utf8Decoder
(
allowMalformed:
true
))
.
listen
((
String
line
)
{
.
listen
((
String
line
)
{
sink
.
write
(
line
);
sink
.
write
(
line
);
});
});
unawaited
(
_loggingProcess
.
exitCode
.
then
<
void
>((
int
exitCode
)
{
unawaited
(
_loggingProcess
!
.
exitCode
.
then
<
void
>((
int
exitCode
)
{
if
(!
_abortedLogging
)
{
if
(!
_abortedLogging
)
{
sink
.
writeln
(
'adb logcat failed with exit code
$exitCode
.
\n
'
);
sink
.
writeln
(
'adb logcat failed with exit code
$exitCode
.
\n
'
);
}
}
...
@@ -617,8 +613,8 @@ class AndroidDevice extends Device {
...
@@ -617,8 +613,8 @@ class AndroidDevice extends Device {
Future
<
void
>
stopLoggingToSink
()
async
{
Future
<
void
>
stopLoggingToSink
()
async
{
if
(
_loggingProcess
!=
null
)
{
if
(
_loggingProcess
!=
null
)
{
_abortedLogging
=
true
;
_abortedLogging
=
true
;
_loggingProcess
.
kill
();
_loggingProcess
!
.
kill
();
await
_loggingProcess
.
exitCode
;
await
_loggingProcess
!
.
exitCode
;
}
}
}
}
...
@@ -629,7 +625,7 @@ class AndroidDevice extends Device {
...
@@ -629,7 +625,7 @@ class AndroidDevice extends Device {
final
Completer
<
void
>
processDone
=
Completer
<
void
>();
final
Completer
<
void
>
processDone
=
Completer
<
void
>();
final
Completer
<
void
>
abort
=
Completer
<
void
>();
final
Completer
<
void
>
abort
=
Completer
<
void
>();
bool
aborted
=
false
;
bool
aborted
=
false
;
StreamController
<
String
>
stream
;
late
final
StreamController
<
String
>
stream
;
stream
=
StreamController
<
String
>(
stream
=
StreamController
<
String
>(
onListen:
()
async
{
onListen:
()
async
{
await
adb
(<
String
>[
'logcat'
,
'--clear'
]);
await
adb
(<
String
>[
'logcat'
,
'--clear'
]);
...
@@ -713,22 +709,22 @@ class IosDeviceDiscovery implements DeviceDiscovery {
...
@@ -713,22 +709,22 @@ class IosDeviceDiscovery implements DeviceDiscovery {
IosDeviceDiscovery
.
_
();
IosDeviceDiscovery
.
_
();
static
IosDeviceDiscovery
_instance
;
static
IosDeviceDiscovery
?
_instance
;
IosDevice
_workingDevice
;
IosDevice
?
_workingDevice
;
@override
@override
Future
<
IosDevice
>
get
workingDevice
async
{
Future
<
IosDevice
>
get
workingDevice
async
{
if
(
_workingDevice
==
null
)
{
if
(
_workingDevice
==
null
)
{
if
(
Platform
.
environment
.
containsKey
(
DeviceIdEnvName
))
{
if
(
Platform
.
environment
.
containsKey
(
DeviceIdEnvName
))
{
final
String
deviceId
=
Platform
.
environment
[
DeviceIdEnvName
];
final
String
deviceId
=
Platform
.
environment
[
DeviceIdEnvName
]
!
;
await
chooseWorkingDeviceById
(
deviceId
);
await
chooseWorkingDeviceById
(
deviceId
);
return
_workingDevice
;
return
_workingDevice
!
;
}
}
await
chooseWorkingDevice
();
await
chooseWorkingDevice
();
}
}
return
_workingDevice
;
return
_workingDevice
!
;
}
}
/// Picks a random iOS device out of connected devices and sets it as
/// Picks a random iOS device out of connected devices and sets it as
...
@@ -749,7 +745,7 @@ class IosDeviceDiscovery implements DeviceDiscovery {
...
@@ -749,7 +745,7 @@ class IosDeviceDiscovery implements DeviceDiscovery {
@override
@override
Future
<
void
>
chooseWorkingDeviceById
(
String
deviceId
)
async
{
Future
<
void
>
chooseWorkingDeviceById
(
String
deviceId
)
async
{
final
String
matchedId
=
_findMatchId
(
await
discoverDevices
(),
deviceId
);
final
String
?
matchedId
=
_findMatchId
(
await
discoverDevices
(),
deviceId
);
if
(
matchedId
!=
null
)
{
if
(
matchedId
!=
null
)
{
_workingDevice
=
IosDevice
(
deviceId:
matchedId
);
_workingDevice
=
IosDevice
(
deviceId:
matchedId
);
print
(
'Choose device by ID:
$matchedId
'
);
print
(
'Choose device by ID:
$matchedId
'
);
...
@@ -824,7 +820,7 @@ class IosDeviceDiscovery implements DeviceDiscovery {
...
@@ -824,7 +820,7 @@ class IosDeviceDiscovery implements DeviceDiscovery {
/// iOS device.
/// iOS device.
class
IosDevice
extends
Device
{
class
IosDevice
extends
Device
{
IosDevice
({
@
required
this
.
deviceId
});
IosDevice
({
required
this
.
deviceId
});
@override
@override
final
String
deviceId
;
final
String
deviceId
;
...
@@ -846,8 +842,8 @@ class IosDevice extends Device {
...
@@ -846,8 +842,8 @@ class IosDevice extends Device {
@override
@override
bool
get
canStreamLogs
=>
true
;
bool
get
canStreamLogs
=>
true
;
bool
_abortedLogging
/*!*/
=
false
;
bool
_abortedLogging
=
false
;
Process
/*?*/
_loggingProcess
;
Process
?
_loggingProcess
;
@override
@override
Future
<
void
>
startLoggingToSink
(
IOSink
sink
,
{
bool
clear
=
true
})
async
{
Future
<
void
>
startLoggingToSink
(
IOSink
sink
,
{
bool
clear
=
true
})
async
{
...
@@ -859,17 +855,17 @@ class IosDevice extends Device {
...
@@ -859,17 +855,17 @@ class IosDevice extends Device {
'DYLD_LIBRARY_PATH'
:
dyldLibraryPath
,
'DYLD_LIBRARY_PATH'
:
dyldLibraryPath
,
},
},
);
);
_loggingProcess
.
stdout
_loggingProcess
!
.
stdout
.
transform
<
String
>(
const
Utf8Decoder
(
allowMalformed:
true
))
.
transform
<
String
>(
const
Utf8Decoder
(
allowMalformed:
true
))
.
listen
((
String
line
)
{
.
listen
((
String
line
)
{
sink
.
write
(
line
);
sink
.
write
(
line
);
});
});
_loggingProcess
.
stderr
_loggingProcess
!
.
stderr
.
transform
<
String
>(
const
Utf8Decoder
(
allowMalformed:
true
))
.
transform
<
String
>(
const
Utf8Decoder
(
allowMalformed:
true
))
.
listen
((
String
line
)
{
.
listen
((
String
line
)
{
sink
.
write
(
line
);
sink
.
write
(
line
);
});
});
unawaited
(
_loggingProcess
.
exitCode
.
then
<
void
>((
int
exitCode
)
{
unawaited
(
_loggingProcess
!
.
exitCode
.
then
<
void
>((
int
exitCode
)
{
if
(!
_abortedLogging
)
{
if
(!
_abortedLogging
)
{
sink
.
writeln
(
'idevicesyslog failed with exit code
$exitCode
.
\n
'
);
sink
.
writeln
(
'idevicesyslog failed with exit code
$exitCode
.
\n
'
);
}
}
...
@@ -880,8 +876,8 @@ class IosDevice extends Device {
...
@@ -880,8 +876,8 @@ class IosDevice extends Device {
Future
<
void
>
stopLoggingToSink
()
async
{
Future
<
void
>
stopLoggingToSink
()
async
{
if
(
_loggingProcess
!=
null
)
{
if
(
_loggingProcess
!=
null
)
{
_abortedLogging
=
true
;
_abortedLogging
=
true
;
_loggingProcess
.
kill
();
_loggingProcess
!
.
kill
();
await
_loggingProcess
.
exitCode
;
await
_loggingProcess
!
.
exitCode
;
}
}
}
}
...
@@ -934,7 +930,7 @@ class IosDevice extends Device {
...
@@ -934,7 +930,7 @@ class IosDevice extends Device {
/// Fuchsia device.
/// Fuchsia device.
class
FuchsiaDevice
extends
Device
{
class
FuchsiaDevice
extends
Device
{
const
FuchsiaDevice
({
@
required
this
.
deviceId
});
const
FuchsiaDevice
({
required
this
.
deviceId
});
@override
@override
final
String
deviceId
;
final
String
deviceId
;
...
@@ -982,7 +978,7 @@ class FuchsiaDevice extends Device {
...
@@ -982,7 +978,7 @@ class FuchsiaDevice extends Device {
/// Path to the `adb` executable.
/// Path to the `adb` executable.
String
get
adbPath
{
String
get
adbPath
{
final
String
androidHome
=
Platform
.
environment
[
'ANDROID_HOME'
]
??
Platform
.
environment
[
'ANDROID_SDK_ROOT'
];
final
String
?
androidHome
=
Platform
.
environment
[
'ANDROID_HOME'
]
??
Platform
.
environment
[
'ANDROID_SDK_ROOT'
];
if
(
androidHome
==
null
)
{
if
(
androidHome
==
null
)
{
throw
const
DeviceException
(
throw
const
DeviceException
(
...
@@ -1001,7 +997,7 @@ String get adbPath {
...
@@ -1001,7 +997,7 @@ String get adbPath {
}
}
class
FakeDevice
extends
Device
{
class
FakeDevice
extends
Device
{
const
FakeDevice
({
@
required
this
.
deviceId
});
const
FakeDevice
({
required
this
.
deviceId
});
@override
@override
final
String
deviceId
;
final
String
deviceId
;
...
@@ -1055,22 +1051,22 @@ class FakeDeviceDiscovery implements DeviceDiscovery {
...
@@ -1055,22 +1051,22 @@ class FakeDeviceDiscovery implements DeviceDiscovery {
FakeDeviceDiscovery
.
_
();
FakeDeviceDiscovery
.
_
();
static
FakeDeviceDiscovery
_instance
;
static
FakeDeviceDiscovery
?
_instance
;
FakeDevice
_workingDevice
;
FakeDevice
?
_workingDevice
;
@override
@override
Future
<
FakeDevice
>
get
workingDevice
async
{
Future
<
FakeDevice
>
get
workingDevice
async
{
if
(
_workingDevice
==
null
)
{
if
(
_workingDevice
==
null
)
{
if
(
Platform
.
environment
.
containsKey
(
DeviceIdEnvName
))
{
if
(
Platform
.
environment
.
containsKey
(
DeviceIdEnvName
))
{
final
String
deviceId
=
Platform
.
environment
[
DeviceIdEnvName
];
final
String
deviceId
=
Platform
.
environment
[
DeviceIdEnvName
]
!
;
await
chooseWorkingDeviceById
(
deviceId
);
await
chooseWorkingDeviceById
(
deviceId
);
return
_workingDevice
;
return
_workingDevice
!
;
}
}
await
chooseWorkingDevice
();
await
chooseWorkingDevice
();
}
}
return
_workingDevice
;
return
_workingDevice
!
;
}
}
/// The Fake is only available for by ID device discovery.
/// The Fake is only available for by ID device discovery.
...
@@ -1081,7 +1077,7 @@ class FakeDeviceDiscovery implements DeviceDiscovery {
...
@@ -1081,7 +1077,7 @@ class FakeDeviceDiscovery implements DeviceDiscovery {
@override
@override
Future
<
void
>
chooseWorkingDeviceById
(
String
deviceId
)
async
{
Future
<
void
>
chooseWorkingDeviceById
(
String
deviceId
)
async
{
final
String
matchedId
=
_findMatchId
(
await
discoverDevices
(),
deviceId
);
final
String
?
matchedId
=
_findMatchId
(
await
discoverDevices
(),
deviceId
);
if
(
matchedId
!=
null
)
{
if
(
matchedId
!=
null
)
{
_workingDevice
=
FakeDevice
(
deviceId:
matchedId
);
_workingDevice
=
FakeDevice
(
deviceId:
matchedId
);
print
(
'Choose device by ID:
$matchedId
'
);
print
(
'Choose device by ID:
$matchedId
'
);
...
...
dev/devicelab/lib/framework/framework.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:developer'
;
import
'dart:developer'
;
...
@@ -64,8 +62,8 @@ class _TaskRunner {
...
@@ -64,8 +62,8 @@ class _TaskRunner {
_TaskRunner
(
this
.
task
)
{
_TaskRunner
(
this
.
task
)
{
registerExtension
(
'ext.cocoonRunTask'
,
registerExtension
(
'ext.cocoonRunTask'
,
(
String
method
,
Map
<
String
,
String
>
parameters
)
async
{
(
String
method
,
Map
<
String
,
String
>
parameters
)
async
{
final
Duration
taskTimeout
=
parameters
.
containsKey
(
'timeoutInMinutes'
)
final
Duration
?
taskTimeout
=
parameters
.
containsKey
(
'timeoutInMinutes'
)
?
Duration
(
minutes:
int
.
parse
(
parameters
[
'timeoutInMinutes'
]))
?
Duration
(
minutes:
int
.
parse
(
parameters
[
'timeoutInMinutes'
]
!
))
:
null
;
:
null
;
// This is only expected to be passed in unit test runs so they do not
// 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.
// kill the Dart process that is running them and waste time running config.
...
@@ -82,7 +80,7 @@ class _TaskRunner {
...
@@ -82,7 +80,7 @@ class _TaskRunner {
final
TaskFunction
task
;
final
TaskFunction
task
;
Future
<
Device
/*?*/
>
_getWorkingDeviceIfAvailable
()
async
{
Future
<
Device
?
>
_getWorkingDeviceIfAvailable
()
async
{
try
{
try
{
return
await
devices
.
workingDevice
;
return
await
devices
.
workingDevice
;
}
on
DeviceException
{
}
on
DeviceException
{
...
@@ -91,8 +89,8 @@ class _TaskRunner {
...
@@ -91,8 +89,8 @@ class _TaskRunner {
}
}
// TODO(ianh): workaround for https://github.com/dart-lang/sdk/issues/23797
// TODO(ianh): workaround for https://github.com/dart-lang/sdk/issues/23797
RawReceivePort
_keepAlivePort
;
RawReceivePort
?
_keepAlivePort
;
Timer
_startTaskTimeout
;
Timer
?
_startTaskTimeout
;
bool
_taskStarted
=
false
;
bool
_taskStarted
=
false
;
final
Completer
<
TaskResult
>
_completer
=
Completer
<
TaskResult
>();
final
Completer
<
TaskResult
>
_completer
=
Completer
<
TaskResult
>();
...
@@ -102,7 +100,7 @@ class _TaskRunner {
...
@@ -102,7 +100,7 @@ class _TaskRunner {
/// Signals that this task runner finished running the task.
/// Signals that this task runner finished running the task.
Future
<
TaskResult
>
get
whenDone
=>
_completer
.
future
;
Future
<
TaskResult
>
get
whenDone
=>
_completer
.
future
;
Future
<
TaskResult
>
run
(
Duration
taskTimeout
,
{
Future
<
TaskResult
>
run
(
Duration
?
taskTimeout
,
{
bool
runFlutterConfig
=
true
,
bool
runFlutterConfig
=
true
,
bool
runProcessCleanup
=
true
,
bool
runProcessCleanup
=
true
,
})
async
{
})
async
{
...
@@ -110,7 +108,7 @@ class _TaskRunner {
...
@@ -110,7 +108,7 @@ class _TaskRunner {
_taskStarted
=
true
;
_taskStarted
=
true
;
print
(
'Running task with a timeout of
$taskTimeout
.'
);
print
(
'Running task with a timeout of
$taskTimeout
.'
);
final
String
exe
=
Platform
.
isWindows
?
'.exe'
:
''
;
final
String
exe
=
Platform
.
isWindows
?
'.exe'
:
''
;
Set
<
RunningProcessInfo
>
beforeRunningDartInstances
;
late
Set
<
RunningProcessInfo
>
beforeRunningDartInstances
;
if
(
runProcessCleanup
)
{
if
(
runProcessCleanup
)
{
section
(
'Checking running Dart
$exe
processes'
);
section
(
'Checking running Dart
$exe
processes'
);
beforeRunningDartInstances
=
await
getRunningProcesses
(
beforeRunningDartInstances
=
await
getRunningProcesses
(
...
@@ -136,7 +134,7 @@ class _TaskRunner {
...
@@ -136,7 +134,7 @@ class _TaskRunner {
'--enable-windows-desktop'
,
'--enable-windows-desktop'
,
'--enable-linux-desktop'
,
'--enable-linux-desktop'
,
'--enable-web'
,
'--enable-web'
,
if
(
localEngine
!=
null
)
...<
String
>[
'--local-engine'
,
localEngine
],
if
(
localEngine
!=
null
)
...<
String
>[
'--local-engine'
,
localEngine
!
],
],
canFail:
true
);
],
canFail:
true
);
if
(
configResult
!=
0
)
{
if
(
configResult
!=
0
)
{
print
(
'Failed to enable configuration, tasks may not run.'
);
print
(
'Failed to enable configuration, tasks may not run.'
);
...
@@ -145,12 +143,12 @@ class _TaskRunner {
...
@@ -145,12 +143,12 @@ class _TaskRunner {
print
(
'Skipping enabling configs for macOS, Linux, Windows, and Web'
);
print
(
'Skipping enabling configs for macOS, Linux, Windows, and Web'
);
}
}
final
Device
/*?*/
device
=
await
_getWorkingDeviceIfAvailable
();
final
Device
?
device
=
await
_getWorkingDeviceIfAvailable
();
/*late*/
TaskResult
result
;
late
TaskResult
result
;
IOSink
/*?*/
sink
;
IOSink
?
sink
;
try
{
try
{
if
(
device
!=
null
&&
device
.
canStreamLogs
&&
hostAgent
.
dumpDirectory
!=
null
)
{
if
(
device
!=
null
&&
device
.
canStreamLogs
&&
hostAgent
.
dumpDirectory
!=
null
)
{
sink
=
File
(
path
.
join
(
hostAgent
.
dumpDirectory
.
path
,
'
${device.deviceId}
.log'
)).
openWrite
();
sink
=
File
(
path
.
join
(
hostAgent
.
dumpDirectory
!
.
path
,
'
${device.deviceId}
.log'
)).
openWrite
();
await
device
.
startLoggingToSink
(
sink
);
await
device
.
startLoggingToSink
(
sink
);
}
}
...
@@ -212,7 +210,7 @@ class _TaskRunner {
...
@@ -212,7 +210,7 @@ class _TaskRunner {
final
File
rebootFile
=
_rebootFile
();
final
File
rebootFile
=
_rebootFile
();
int
runCount
;
int
runCount
;
if
(
rebootFile
.
existsSync
())
{
if
(
rebootFile
.
existsSync
())
{
runCount
=
int
.
tryParse
(
rebootFile
.
readAsStringSync
().
trim
());
runCount
=
int
.
tryParse
(
rebootFile
.
readAsStringSync
().
trim
())
??
0
;
}
else
{
}
else
{
runCount
=
0
;
runCount
=
0
;
}
}
...
@@ -283,10 +281,10 @@ class _TaskRunner {
...
@@ -283,10 +281,10 @@ class _TaskRunner {
File
_rebootFile
(
)
{
File
_rebootFile
(
)
{
if
(
Platform
.
isLinux
||
Platform
.
isMacOS
)
{
if
(
Platform
.
isLinux
||
Platform
.
isMacOS
)
{
return
File
(
path
.
join
(
Platform
.
environment
[
'HOME'
],
'.reboot-count'
));
return
File
(
path
.
join
(
Platform
.
environment
[
'HOME'
]
!
,
'.reboot-count'
));
}
}
if
(!
Platform
.
isWindows
)
{
if
(!
Platform
.
isWindows
)
{
throw
StateError
(
'Unexpected platform
${Platform.operatingSystem}
'
);
throw
StateError
(
'Unexpected platform
${Platform.operatingSystem}
'
);
}
}
return
File
(
path
.
join
(
Platform
.
environment
[
'USERPROFILE'
],
'.reboot-count'
));
return
File
(
path
.
join
(
Platform
.
environment
[
'USERPROFILE'
]
!
,
'.reboot-count'
));
}
}
dev/devicelab/lib/framework/ios.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:convert'
;
import
'dart:convert'
;
import
'utils.dart'
;
import
'utils.dart'
;
...
@@ -42,17 +40,10 @@ Future<bool> containsBitcode(String pathToBinary) async {
...
@@ -42,17 +40,10 @@ Future<bool> containsBitcode(String pathToBinary) async {
final
List
<
String
>
lines
=
LineSplitter
.
split
(
loadCommands
).
toList
();
final
List
<
String
>
lines
=
LineSplitter
.
split
(
loadCommands
).
toList
();
lines
.
asMap
().
forEach
((
int
index
,
String
line
)
{
lines
.
asMap
().
forEach
((
int
index
,
String
line
)
{
if
(
line
.
contains
(
'segname __LLVM'
)
&&
lines
.
length
-
index
-
1
>
3
)
{
if
(
line
.
contains
(
'segname __LLVM'
)
&&
lines
.
length
-
index
-
1
>
3
)
{
final
String
emptyBitcodeMarker
=
lines
emptyBitcodeMarkerFound
|
=
lines
.
skip
(
index
-
1
)
.
skip
(
index
-
1
)
.
take
(
4
)
.
take
(
4
)
.
firstWhere
(
.
any
((
String
line
)
=>
line
.
contains
(
' size 0x0000000000000001'
));
(
String
line
)
=>
line
.
contains
(
' size 0x0000000000000001'
),
orElse:
()
=>
null
,
);
if
(
emptyBitcodeMarker
!=
null
)
{
emptyBitcodeMarkerFound
=
true
;
return
;
}
}
}
});
});
return
!
emptyBitcodeMarkerFound
;
return
!
emptyBitcodeMarkerFound
;
...
@@ -79,16 +70,16 @@ Future<void> testWithNewIOSSimulator(
...
@@ -79,16 +70,16 @@ Future<void> testWithNewIOSSimulator(
workingDirectory:
flutterDirectory
.
path
,
workingDirectory:
flutterDirectory
.
path
,
);
);
String
iOSSimRuntime
;
String
?
iOSSimRuntime
;
final
RegExp
iOSRuntimePattern
=
RegExp
(
r'iOS .*\) - (.*)'
);
final
RegExp
iOSRuntimePattern
=
RegExp
(
r'iOS .*\) - (.*)'
);
for
(
final
String
runtime
in
LineSplitter
.
split
(
availableRuntimes
))
{
for
(
final
String
runtime
in
LineSplitter
.
split
(
availableRuntimes
))
{
// These seem to be in order, so allow matching multiple lines so it grabs
// These seem to be in order, so allow matching multiple lines so it grabs
// the last (hopefully latest) one.
// the last (hopefully latest) one.
final
RegExpMatch
iOSRuntimeMatch
=
iOSRuntimePattern
.
firstMatch
(
runtime
);
final
RegExpMatch
?
iOSRuntimeMatch
=
iOSRuntimePattern
.
firstMatch
(
runtime
);
if
(
iOSRuntimeMatch
!=
null
)
{
if
(
iOSRuntimeMatch
!=
null
)
{
iOSSimRuntime
=
iOSRuntimeMatch
.
group
(
1
).
trim
();
iOSSimRuntime
=
iOSRuntimeMatch
.
group
(
1
)
!
.
trim
();
continue
;
continue
;
}
}
}
}
...
...
dev/devicelab/lib/framework/manifest.dart
View file @
ef5ffd08
...
@@ -2,17 +2,14 @@
...
@@ -2,17 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
;
import
'dart:io'
;
import
'package:meta/meta.dart'
;
import
'package:yaml/yaml.dart'
;
import
'package:yaml/yaml.dart'
;
import
'utils.dart'
;
import
'utils.dart'
;
/// Loads manifest data from `manifest.yaml` file or from [yaml], if present.
/// Loads manifest data from `manifest.yaml` file or from [yaml], if present.
Manifest
loadTaskManifest
(
[
String
yaml
])
{
Manifest
loadTaskManifest
(
[
String
?
yaml
])
{
final
dynamic
manifestYaml
=
yaml
==
null
final
dynamic
manifestYaml
=
yaml
==
null
?
loadYaml
(
file
(
'manifest.yaml'
).
readAsStringSync
())
?
loadYaml
(
file
(
'manifest.yaml'
).
readAsStringSync
())
:
loadYamlNode
(
yaml
);
:
loadYamlNode
(
yaml
);
...
@@ -32,13 +29,13 @@ class Manifest {
...
@@ -32,13 +29,13 @@ class Manifest {
/// A CI task.
/// A CI task.
class
ManifestTask
{
class
ManifestTask
{
ManifestTask
.
_
({
ManifestTask
.
_
({
@
required
this
.
name
,
required
this
.
name
,
@
required
this
.
description
,
required
this
.
description
,
@
required
this
.
stage
,
required
this
.
stage
,
@
required
this
.
requiredAgentCapabilities
,
required
this
.
requiredAgentCapabilities
,
@
required
this
.
isFlaky
,
required
this
.
isFlaky
,
@
required
this
.
timeoutInMinutes
,
required
this
.
timeoutInMinutes
,
@
required
this
.
onLuci
,
required
this
.
onLuci
,
})
{
})
{
final
String
taskName
=
'task "
$name
"'
;
final
String
taskName
=
'task "
$name
"'
;
_checkIsNotBlank
(
name
,
'Task name'
,
taskName
);
_checkIsNotBlank
(
name
,
'Task name'
,
taskName
);
...
@@ -148,9 +145,9 @@ ManifestTask _validateAndParseTask(String taskName, dynamic taskYaml) {
...
@@ -148,9 +145,9 @@ ManifestTask _validateAndParseTask(String taskName, dynamic taskYaml) {
// ignore: avoid_dynamic_calls
// ignore: avoid_dynamic_calls
stage:
taskYaml
[
'stage'
]
as
String
,
stage:
taskYaml
[
'stage'
]
as
String
,
requiredAgentCapabilities:
capabilities
as
List
<
String
>,
requiredAgentCapabilities:
capabilities
as
List
<
String
>,
isFlaky:
isFlaky
as
bool
??
false
,
isFlaky:
isFlaky
as
bool
,
timeoutInMinutes:
timeoutInMinutes
as
int
,
timeoutInMinutes:
timeoutInMinutes
as
int
,
onLuci:
onLuci
as
bool
??
false
,
onLuci:
onLuci
as
bool
,
);
);
}
}
...
@@ -161,7 +158,7 @@ List<String> _validateAndParseCapabilities(String taskName, dynamic capabilities
...
@@ -161,7 +158,7 @@ List<String> _validateAndParseCapabilities(String taskName, dynamic capabilities
final
dynamic
capability
=
capabilities
[
i
];
final
dynamic
capability
=
capabilities
[
i
];
_checkType
(
capability
is
String
,
capability
,
'required_agent_capabilities[
$i
]'
,
'string'
);
_checkType
(
capability
is
String
,
capability
,
'required_agent_capabilities[
$i
]'
,
'string'
);
}
}
return
(
capabilitiesYaml
as
List
<
dynamic
>)
.
cast
<
String
>();
return
capabilitiesYaml
.
cast
<
String
>();
}
}
void
_checkType
(
bool
isValid
,
dynamic
value
,
String
variableName
,
String
typeName
)
{
void
_checkType
(
bool
isValid
,
dynamic
value
,
String
variableName
,
String
typeName
)
{
...
...
dev/devicelab/lib/framework/runner.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:io'
;
...
@@ -21,13 +19,13 @@ Future<void> runTasks(
...
@@ -21,13 +19,13 @@ Future<void> runTasks(
List
<
String
>
taskNames
,
{
List
<
String
>
taskNames
,
{
bool
exitOnFirstTestFailure
=
false
,
bool
exitOnFirstTestFailure
=
false
,
bool
silent
=
false
,
bool
silent
=
false
,
String
deviceId
,
String
?
deviceId
,
String
gitBranch
,
String
?
gitBranch
,
String
localEngine
,
String
?
localEngine
,
String
localEngineSrcPath
,
String
?
localEngineSrcPath
,
String
luciBuilder
,
String
?
luciBuilder
,
String
resultsPath
,
String
?
resultsPath
,
List
<
String
>
taskArgs
,
List
<
String
>
?
taskArgs
,
})
async
{
})
async
{
for
(
final
String
taskName
in
taskNames
)
{
for
(
final
String
taskName
in
taskNames
)
{
section
(
'Running task "
$taskName
"'
);
section
(
'Running task "
$taskName
"'
);
...
@@ -44,7 +42,7 @@ Future<void> runTasks(
...
@@ -44,7 +42,7 @@ Future<void> runTasks(
print
(
const
JsonEncoder
.
withIndent
(
' '
).
convert
(
result
));
print
(
const
JsonEncoder
.
withIndent
(
' '
).
convert
(
result
));
section
(
'Finished task "
$taskName
"'
);
section
(
'Finished task "
$taskName
"'
);
if
(
resultsPath
!=
null
)
{
if
(
resultsPath
!=
null
&&
gitBranch
!=
null
)
{
final
Cocoon
cocoon
=
Cocoon
();
final
Cocoon
cocoon
=
Cocoon
();
await
cocoon
.
writeTaskResultToFile
(
await
cocoon
.
writeTaskResultToFile
(
builderName:
luciBuilder
,
builderName:
luciBuilder
,
...
@@ -76,11 +74,11 @@ Future<void> runTasks(
...
@@ -76,11 +74,11 @@ Future<void> runTasks(
Future
<
TaskResult
>
runTask
(
Future
<
TaskResult
>
runTask
(
String
taskName
,
{
String
taskName
,
{
bool
silent
=
false
,
bool
silent
=
false
,
String
localEngine
,
String
?
localEngine
,
String
localEngineSrcPath
,
String
?
localEngineSrcPath
,
String
deviceId
,
String
?
deviceId
,
List
<
String
>
taskArgs
,
List
<
String
>
?
taskArgs
,
@visibleForTesting
Map
<
String
,
String
>
isolateParams
,
@visibleForTesting
Map
<
String
,
String
>
?
isolateParams
,
})
async
{
})
async
{
final
String
taskExecutable
=
'bin/tasks/
$taskName
.dart'
;
final
String
taskExecutable
=
'bin/tasks/
$taskName
.dart'
;
...
@@ -117,7 +115,7 @@ Future<TaskResult> runTask(
...
@@ -117,7 +115,7 @@ Future<TaskResult> runTask(
.
transform
<
String
>(
const
LineSplitter
())
.
transform
<
String
>(
const
LineSplitter
())
.
listen
((
String
line
)
{
.
listen
((
String
line
)
{
if
(!
uri
.
isCompleted
)
{
if
(!
uri
.
isCompleted
)
{
final
Uri
serviceUri
=
parseServiceUri
(
line
,
prefix:
'Observatory listening on '
);
final
Uri
?
serviceUri
=
parseServiceUri
(
line
,
prefix:
'Observatory listening on '
);
if
(
serviceUri
!=
null
)
if
(
serviceUri
!=
null
)
uri
.
complete
(
serviceUri
);
uri
.
complete
(
serviceUri
);
}
}
...
@@ -139,7 +137,7 @@ Future<TaskResult> runTask(
...
@@ -139,7 +137,7 @@ Future<TaskResult> runTask(
'ext.cocoonRunTask'
,
'ext.cocoonRunTask'
,
args:
isolateParams
,
args:
isolateParams
,
isolateId:
result
.
isolate
.
id
,
isolateId:
result
.
isolate
.
id
,
)).
json
;
)).
json
!
;
final
TaskResult
taskResult
=
TaskResult
.
fromJson
(
taskResultJson
);
final
TaskResult
taskResult
=
TaskResult
.
fromJson
(
taskResultJson
);
await
runner
.
exitCode
;
await
runner
.
exitCode
;
return
taskResult
;
return
taskResult
;
...
@@ -168,13 +166,13 @@ Future<ConnectionResult> _connectToRunnerIsolate(Uri vmServiceUri) async {
...
@@ -168,13 +166,13 @@ Future<ConnectionResult> _connectToRunnerIsolate(Uri vmServiceUri) async {
// Look up the isolate.
// Look up the isolate.
final
VmService
client
=
await
vmServiceConnectUri
(
url
);
final
VmService
client
=
await
vmServiceConnectUri
(
url
);
VM
vm
=
await
client
.
getVM
();
VM
vm
=
await
client
.
getVM
();
while
(
vm
.
isolates
.
isEmpty
)
{
while
(
vm
.
isolates
!
.
isEmpty
)
{
await
Future
<
void
>.
delayed
(
const
Duration
(
seconds:
1
));
await
Future
<
void
>.
delayed
(
const
Duration
(
seconds:
1
));
vm
=
await
client
.
getVM
();
vm
=
await
client
.
getVM
();
}
}
final
IsolateRef
isolate
=
vm
.
isolates
.
first
;
final
IsolateRef
isolate
=
vm
.
isolates
!
.
first
;
final
Response
response
=
await
client
.
callServiceExtension
(
'ext.cocoonRunnerReady'
,
isolateId:
isolate
.
id
);
final
Response
response
=
await
client
.
callServiceExtension
(
'ext.cocoonRunnerReady'
,
isolateId:
isolate
.
id
);
if
(
response
.
json
[
'response'
]
!=
'ready'
)
if
(
response
.
json
!
[
'response'
]
!=
'ready'
)
throw
'not ready yet'
;
throw
'not ready yet'
;
return
ConnectionResult
(
client
,
isolate
);
return
ConnectionResult
(
client
,
isolate
);
}
catch
(
error
)
{
}
catch
(
error
)
{
...
@@ -193,7 +191,7 @@ class ConnectionResult {
...
@@ -193,7 +191,7 @@ class ConnectionResult {
}
}
/// The cocoon client sends an invalid VM service response, we need to intercept it.
/// The cocoon client sends an invalid VM service response, we need to intercept it.
Future
<
VmService
>
vmServiceConnectUri
(
String
wsUri
,
{
Log
log
})
async
{
Future
<
VmService
>
vmServiceConnectUri
(
String
wsUri
,
{
Log
?
log
})
async
{
final
WebSocket
socket
=
await
WebSocket
.
connect
(
wsUri
);
final
WebSocket
socket
=
await
WebSocket
.
connect
(
wsUri
);
final
StreamController
<
dynamic
>
controller
=
StreamController
<
dynamic
>();
final
StreamController
<
dynamic
>
controller
=
StreamController
<
dynamic
>();
final
Completer
<
dynamic
>
streamClosedCompleter
=
Completer
<
dynamic
>();
final
Completer
<
dynamic
>
streamClosedCompleter
=
Completer
<
dynamic
>();
...
@@ -207,7 +205,7 @@ Future<VmService> vmServiceConnectUri(String wsUri, {Log log}) async {
...
@@ -207,7 +205,7 @@ Future<VmService> vmServiceConnectUri(String wsUri, {Log log}) async {
controller
.
add
(
data
);
controller
.
add
(
data
);
}
}
},
},
onError:
(
dynamic
err
,
StackTrace
stackTrace
)
=>
controller
.
addError
(
err
,
stackTrace
),
onError:
(
Object
err
,
StackTrace
stackTrace
)
=>
controller
.
addError
(
err
,
stackTrace
),
onDone:
()
=>
streamClosedCompleter
.
complete
(),
onDone:
()
=>
streamClosedCompleter
.
complete
(),
);
);
...
...
dev/devicelab/lib/framework/running_processes.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
;
import
'dart:io'
;
import
'package:meta/meta.dart'
;
import
'package:meta/meta.dart'
;
...
@@ -36,7 +34,7 @@ class RunningProcessInfo {
...
@@ -36,7 +34,7 @@ class RunningProcessInfo {
}
}
}
}
Future
<
bool
>
killProcess
(
String
pid
,
{
ProcessManager
processManager
})
async
{
Future
<
bool
>
killProcess
(
String
pid
,
{
ProcessManager
?
processManager
})
async
{
assert
(
pid
!=
null
,
'Must specify a pid to kill'
);
assert
(
pid
!=
null
,
'Must specify a pid to kill'
);
processManager
??=
const
LocalProcessManager
();
processManager
??=
const
LocalProcessManager
();
ProcessResult
result
;
ProcessResult
result
;
...
@@ -58,8 +56,8 @@ Future<bool> killProcess(String pid, {ProcessManager processManager}) async {
...
@@ -58,8 +56,8 @@ Future<bool> killProcess(String pid, {ProcessManager processManager}) async {
}
}
Stream
<
RunningProcessInfo
>
getRunningProcesses
({
Stream
<
RunningProcessInfo
>
getRunningProcesses
({
String
processName
,
String
?
processName
,
ProcessManager
processManager
,
ProcessManager
?
processManager
,
})
{
})
{
processManager
??=
const
LocalProcessManager
();
processManager
??=
const
LocalProcessManager
();
if
(
Platform
.
isWindows
)
{
if
(
Platform
.
isWindows
)
{
...
@@ -69,7 +67,7 @@ Stream<RunningProcessInfo> getRunningProcesses({
...
@@ -69,7 +67,7 @@ Stream<RunningProcessInfo> getRunningProcesses({
}
}
@visibleForTesting
@visibleForTesting
Stream
<
RunningProcessInfo
>
windowsRunningProcesses
(
String
processName
)
async
*
{
Stream
<
RunningProcessInfo
>
windowsRunningProcesses
(
String
?
processName
)
async
*
{
// PowerShell script to get the command line arguments and create time of
// PowerShell script to get the command line arguments and create time of
// a process.
// a process.
// See: https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-process
// See: https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-process
...
@@ -107,8 +105,8 @@ Iterable<RunningProcessInfo> processPowershellOutput(String output) sync* {
...
@@ -107,8 +105,8 @@ Iterable<RunningProcessInfo> processPowershellOutput(String output) sync* {
const
int
processIdHeaderSize
=
'ProcessId'
.
length
;
const
int
processIdHeaderSize
=
'ProcessId'
.
length
;
const
int
creationDateHeaderStart
=
processIdHeaderSize
+
1
;
const
int
creationDateHeaderStart
=
processIdHeaderSize
+
1
;
int
creationDateHeaderEnd
;
late
int
creationDateHeaderEnd
;
int
commandLineHeaderStart
;
late
int
commandLineHeaderStart
;
bool
inTableBody
=
false
;
bool
inTableBody
=
false
;
for
(
final
String
line
in
output
.
split
(
'
\n
'
))
{
for
(
final
String
line
in
output
.
split
(
'
\n
'
))
{
if
(
line
.
startsWith
(
'ProcessId'
))
{
if
(
line
.
startsWith
(
'ProcessId'
))
{
...
@@ -160,7 +158,7 @@ Iterable<RunningProcessInfo> processPowershellOutput(String output) sync* {
...
@@ -160,7 +158,7 @@ Iterable<RunningProcessInfo> processPowershellOutput(String output) sync* {
@visibleForTesting
@visibleForTesting
Stream
<
RunningProcessInfo
>
posixRunningProcesses
(
Stream
<
RunningProcessInfo
>
posixRunningProcesses
(
String
processName
,
String
?
processName
,
ProcessManager
processManager
,
ProcessManager
processManager
,
)
async
*
{
)
async
*
{
// Cirrus is missing this in Linux for some reason.
// Cirrus is missing this in Linux for some reason.
...
@@ -194,7 +192,7 @@ Stream<RunningProcessInfo> posixRunningProcesses(
...
@@ -194,7 +192,7 @@ Stream<RunningProcessInfo> posixRunningProcesses(
@visibleForTesting
@visibleForTesting
Iterable
<
RunningProcessInfo
>
processPsOutput
(
Iterable
<
RunningProcessInfo
>
processPsOutput
(
String
output
,
String
output
,
String
processName
,
String
?
processName
,
)
sync
*
{
)
sync
*
{
if
(
output
==
null
)
{
if
(
output
==
null
)
{
return
;
return
;
...
@@ -235,7 +233,7 @@ Iterable<RunningProcessInfo> processPsOutput(
...
@@ -235,7 +233,7 @@ Iterable<RunningProcessInfo> processPsOutput(
final
String
rawTime
=
line
.
substring
(
0
,
24
);
final
String
rawTime
=
line
.
substring
(
0
,
24
);
final
String
year
=
rawTime
.
substring
(
20
,
24
);
final
String
year
=
rawTime
.
substring
(
20
,
24
);
final
String
month
=
months
[
rawTime
.
substring
(
4
,
7
)];
final
String
month
=
months
[
rawTime
.
substring
(
4
,
7
)]
!
;
final
String
day
=
rawTime
.
substring
(
8
,
10
).
replaceFirst
(
' '
,
'0'
);
final
String
day
=
rawTime
.
substring
(
8
,
10
).
replaceFirst
(
' '
,
'0'
);
final
String
time
=
rawTime
.
substring
(
11
,
19
);
final
String
time
=
rawTime
.
substring
(
11
,
19
);
...
...
dev/devicelab/lib/framework/task_result.dart
View file @
ef5ffd08
...
@@ -41,7 +41,7 @@ class TaskResult {
...
@@ -41,7 +41,7 @@ class TaskResult {
List
<
String
>
detailFiles
=
const
<
String
>[],
List
<
String
>
detailFiles
=
const
<
String
>[],
})
{
})
{
return
TaskResult
.
success
(
return
TaskResult
.
success
(
json
.
decode
(
file
.
readAsStringSync
())
as
Map
<
String
,
dynamic
>,
json
.
decode
(
file
.
readAsStringSync
())
as
Map
<
String
,
dynamic
>
?
,
benchmarkScoreKeys:
benchmarkScoreKeys
,
benchmarkScoreKeys:
benchmarkScoreKeys
,
detailFiles:
detailFiles
,
detailFiles:
detailFiles
,
);
);
...
@@ -53,14 +53,14 @@ class TaskResult {
...
@@ -53,14 +53,14 @@ class TaskResult {
if
(
success
)
{
if
(
success
)
{
final
List
<
String
>
benchmarkScoreKeys
=
(
json
[
'benchmarkScoreKeys'
]
as
List
<
dynamic
>?
??
<
String
>[]).
cast
<
String
>();
final
List
<
String
>
benchmarkScoreKeys
=
(
json
[
'benchmarkScoreKeys'
]
as
List
<
dynamic
>?
??
<
String
>[]).
cast
<
String
>();
final
List
<
String
>
detailFiles
=
(
json
[
'detailFiles'
]
as
List
<
dynamic
>?
??
<
String
>[]).
cast
<
String
>();
final
List
<
String
>
detailFiles
=
(
json
[
'detailFiles'
]
as
List
<
dynamic
>?
??
<
String
>[]).
cast
<
String
>();
return
TaskResult
.
success
(
json
[
'data'
]
as
Map
<
String
,
dynamic
>,
return
TaskResult
.
success
(
json
[
'data'
]
as
Map
<
String
,
dynamic
>
?
,
benchmarkScoreKeys:
benchmarkScoreKeys
,
benchmarkScoreKeys:
benchmarkScoreKeys
,
detailFiles:
detailFiles
,
detailFiles:
detailFiles
,
message:
json
[
'reason'
]
as
String
,
message:
json
[
'reason'
]
as
String
?
,
);
);
}
}
return
TaskResult
.
failure
(
json
[
'reason'
]
as
String
);
return
TaskResult
.
failure
(
json
[
'reason'
]
as
String
?
);
}
}
/// Constructs an unsuccessful result.
/// Constructs an unsuccessful result.
...
@@ -88,7 +88,7 @@ class TaskResult {
...
@@ -88,7 +88,7 @@ class TaskResult {
bool
get
failed
=>
!
succeeded
;
bool
get
failed
=>
!
succeeded
;
/// Explains the result in a human-readable format.
/// Explains the result in a human-readable format.
final
String
message
;
final
String
?
message
;
/// Serializes this task result to JSON format.
/// Serializes this task result to JSON format.
///
///
...
@@ -124,7 +124,7 @@ class TaskResult {
...
@@ -124,7 +124,7 @@ class TaskResult {
}
}
@override
@override
String
toString
()
=>
message
;
String
toString
()
=>
message
??
''
;
}
}
class
TaskResultCheckProcesses
extends
TaskResult
{
class
TaskResultCheckProcesses
extends
TaskResult
{
...
...
dev/devicelab/lib/framework/utils.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:io'
;
...
@@ -11,7 +9,6 @@ import 'dart:math' as math;
...
@@ -11,7 +9,6 @@ import 'dart:math' as math;
import
'package:flutter_devicelab/common.dart'
;
import
'package:flutter_devicelab/common.dart'
;
import
'package:flutter_devicelab/framework/devices.dart'
;
import
'package:flutter_devicelab/framework/devices.dart'
;
import
'package:meta/meta.dart'
;
import
'package:path/path.dart'
as
path
;
import
'package:path/path.dart'
as
path
;
import
'package:process/process.dart'
;
import
'package:process/process.dart'
;
import
'package:stack_trace/stack_trace.dart'
;
import
'package:stack_trace/stack_trace.dart'
;
...
@@ -23,7 +20,7 @@ import 'task_result.dart';
...
@@ -23,7 +20,7 @@ import 'task_result.dart';
String
cwd
=
Directory
.
current
.
path
;
String
cwd
=
Directory
.
current
.
path
;
/// The local engine to use for [flutter] and [evalFlutter], if any.
/// The local engine to use for [flutter] and [evalFlutter], if any.
String
get
localEngine
{
String
?
get
localEngine
{
// Use two distinct `defaultValue`s to determine whether a 'localEngine'
// Use two distinct `defaultValue`s to determine whether a 'localEngine'
// declaration exists in the environment.
// declaration exists in the environment.
const
bool
isDefined
=
const
bool
isDefined
=
...
@@ -34,7 +31,7 @@ String get localEngine {
...
@@ -34,7 +31,7 @@ String get localEngine {
/// The local engine source path to use if a local engine is used for [flutter]
/// The local engine source path to use if a local engine is used for [flutter]
/// and [evalFlutter].
/// and [evalFlutter].
String
get
localEngineSrcPath
{
String
?
get
localEngineSrcPath
{
// Use two distinct `defaultValue`s to determine whether a
// Use two distinct `defaultValue`s to determine whether a
// 'localEngineSrcPath' declaration exists in the environment.
// 'localEngineSrcPath' declaration exists in the environment.
const
bool
isDefined
=
const
bool
isDefined
=
...
@@ -70,18 +67,18 @@ class HealthCheckResult {
...
@@ -70,18 +67,18 @@ class HealthCheckResult {
HealthCheckResult
.
failure
(
this
.
details
)
:
succeeded
=
false
;
HealthCheckResult
.
failure
(
this
.
details
)
:
succeeded
=
false
;
HealthCheckResult
.
error
(
dynamic
error
,
dynamic
stackTrace
)
HealthCheckResult
.
error
(
dynamic
error
,
dynamic
stackTrace
)
:
succeeded
=
false
,
:
succeeded
=
false
,
details
=
'ERROR:
$error${
'\n$stackTrace' ??
''}
'
;
details
=
'ERROR:
$error${
stackTrace != null ? '\n$stackTrace' :
''}
'
;
final
bool
succeeded
;
final
bool
succeeded
;
final
String
details
;
final
String
?
details
;
@override
@override
String
toString
()
{
String
toString
()
{
final
StringBuffer
buf
=
StringBuffer
(
succeeded
?
'succeeded'
:
'failed'
);
final
StringBuffer
buf
=
StringBuffer
(
succeeded
?
'succeeded'
:
'failed'
);
if
(
details
!=
null
&&
details
.
trim
().
isNotEmpty
)
{
if
(
details
!=
null
&&
details
!
.
trim
().
isNotEmpty
)
{
buf
.
writeln
();
buf
.
writeln
();
// Indent details by 4 spaces
// Indent details by 4 spaces
for
(
final
String
line
in
details
.
trim
().
split
(
'
\n
'
))
{
for
(
final
String
line
in
details
!
.
trim
().
split
(
'
\n
'
))
{
buf
.
writeln
(
'
$line
'
);
buf
.
writeln
(
'
$line
'
);
}
}
}
}
...
@@ -127,7 +124,7 @@ Directory dir(String path) => Directory(path);
...
@@ -127,7 +124,7 @@ Directory dir(String path) => Directory(path);
File
file
(
String
path
)
=>
File
(
path
);
File
file
(
String
path
)
=>
File
(
path
);
void
copy
(
File
sourceFile
,
Directory
targetDirectory
,
{
String
name
})
{
void
copy
(
File
sourceFile
,
Directory
targetDirectory
,
{
String
?
name
})
{
final
File
target
=
file
(
final
File
target
=
file
(
path
.
join
(
targetDirectory
.
path
,
name
??
path
.
basename
(
sourceFile
.
path
)));
path
.
join
(
targetDirectory
.
path
,
name
??
path
.
basename
(
sourceFile
.
path
)));
target
.
writeAsBytesSync
(
sourceFile
.
readAsBytesSync
());
target
.
writeAsBytesSync
(
sourceFile
.
readAsBytesSync
());
...
@@ -154,7 +151,7 @@ void recursiveCopy(Directory source, Directory target) {
...
@@ -154,7 +151,7 @@ void recursiveCopy(Directory source, Directory target) {
}
}
FileSystemEntity
move
(
FileSystemEntity
whatToMove
,
FileSystemEntity
move
(
FileSystemEntity
whatToMove
,
{
Directory
to
,
String
name
})
{
{
required
Directory
to
,
String
?
name
})
{
return
whatToMove
return
whatToMove
.
renameSync
(
path
.
join
(
to
.
path
,
name
??
path
.
basename
(
whatToMove
.
path
)));
.
renameSync
(
path
.
join
(
to
.
path
,
name
??
path
.
basename
(
whatToMove
.
path
)));
}
}
...
@@ -225,9 +222,9 @@ Future<String> getDartVersion() async {
...
@@ -225,9 +222,9 @@ Future<String> getDartVersion() async {
return
version
.
replaceAll
(
'"'
,
"'"
);
return
version
.
replaceAll
(
'"'
,
"'"
);
}
}
Future
<
String
>
getCurrentFlutterRepoCommit
()
{
Future
<
String
?
>
getCurrentFlutterRepoCommit
()
{
if
(!
dir
(
'
${flutterDirectory.path}
/.git'
).
existsSync
())
{
if
(!
dir
(
'
${flutterDirectory.path}
/.git'
).
existsSync
())
{
return
Future
<
String
>.
value
(
null
);
return
Future
<
String
?
>.
value
(
null
);
}
}
return
inDirectory
<
String
>(
flutterDirectory
,
()
{
return
inDirectory
<
String
>(
flutterDirectory
,
()
{
...
@@ -275,10 +272,10 @@ Future<DateTime> getFlutterRepoCommitTimestamp(String commit) {
...
@@ -275,10 +272,10 @@ Future<DateTime> getFlutterRepoCommitTimestamp(String commit) {
/// returned in the form of a [Future] that completes to a [Process] object.
/// returned in the form of a [Future] that completes to a [Process] object.
Future
<
Process
>
startProcess
(
Future
<
Process
>
startProcess
(
String
executable
,
String
executable
,
List
<
String
>
arguments
,
{
List
<
String
>
?
arguments
,
{
Map
<
String
,
String
>
environment
,
Map
<
String
,
String
>
?
environment
,
bool
isBot
=
true
,
// set to false to pretend not to be on a bot (e.g. to test user-facing outputs)
bool
isBot
=
true
,
// set to false to pretend not to be on a bot (e.g. to test user-facing outputs)
String
workingDirectory
,
String
?
workingDirectory
,
})
async
{
})
async
{
assert
(
isBot
!=
null
);
assert
(
isBot
!=
null
);
final
String
command
=
'
$executable
${arguments?.join(" ") ?? ""}
'
;
final
String
command
=
'
$executable
${arguments?.join(" ") ?? ""}
'
;
...
@@ -288,7 +285,7 @@ Future<Process> startProcess(
...
@@ -288,7 +285,7 @@ Future<Process> startProcess(
newEnvironment
[
'LANG'
]
=
'en_US.UTF-8'
;
newEnvironment
[
'LANG'
]
=
'en_US.UTF-8'
;
print
(
'
\n
Executing:
$command
in
$finalWorkingDirectory
with environment
$newEnvironment
'
);
print
(
'
\n
Executing:
$command
in
$finalWorkingDirectory
with environment
$newEnvironment
'
);
final
Process
process
=
await
_processManager
.
start
(
final
Process
process
=
await
_processManager
.
start
(
<
String
>[
executable
,
...
arguments
],
<
String
>[
executable
,
...
?
arguments
],
environment:
newEnvironment
,
environment:
newEnvironment
,
workingDirectory:
finalWorkingDirectory
,
workingDirectory:
finalWorkingDirectory
,
);
);
...
@@ -324,9 +321,9 @@ Future<void> forceQuitRunningProcesses() async {
...
@@ -324,9 +321,9 @@ Future<void> forceQuitRunningProcesses() async {
Future
<
int
>
exec
(
Future
<
int
>
exec
(
String
executable
,
String
executable
,
List
<
String
>
arguments
,
{
List
<
String
>
arguments
,
{
Map
<
String
,
String
>
environment
,
Map
<
String
,
String
>
?
environment
,
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
String
workingDirectory
,
String
?
workingDirectory
,
})
async
{
})
async
{
return
_execute
(
return
_execute
(
executable
,
executable
,
...
@@ -340,11 +337,11 @@ Future<int> exec(
...
@@ -340,11 +337,11 @@ Future<int> exec(
Future
<
int
>
_execute
(
Future
<
int
>
_execute
(
String
executable
,
String
executable
,
List
<
String
>
arguments
,
{
List
<
String
>
arguments
,
{
Map
<
String
,
String
>
environment
,
Map
<
String
,
String
>
?
environment
,
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
String
workingDirectory
,
String
?
workingDirectory
,
StringBuffer
output
,
// if not null, the stdout will be written here
StringBuffer
?
output
,
// if not null, the stdout will be written here
StringBuffer
stderr
,
// if not null, the stderr will be written here
StringBuffer
?
stderr
,
// if not null, the stderr will be written here
bool
printStdout
=
true
,
bool
printStdout
=
true
,
bool
printStderr
=
true
,
bool
printStderr
=
true
,
})
async
{
})
async
{
...
@@ -376,8 +373,8 @@ Future<int> _execute(
...
@@ -376,8 +373,8 @@ Future<int> _execute(
/// Returns a future that completes when both out and error streams a closed.
/// Returns a future that completes when both out and error streams a closed.
Future
<
void
>
forwardStandardStreams
(
Future
<
void
>
forwardStandardStreams
(
Process
process
,
{
Process
process
,
{
StringBuffer
output
,
StringBuffer
?
output
,
StringBuffer
stderr
,
StringBuffer
?
stderr
,
bool
printStdout
=
true
,
bool
printStdout
=
true
,
bool
printStderr
=
true
,
bool
printStderr
=
true
,
})
{
})
{
...
@@ -414,10 +411,10 @@ Future<void> forwardStandardStreams(
...
@@ -414,10 +411,10 @@ Future<void> forwardStandardStreams(
Future
<
String
>
eval
(
Future
<
String
>
eval
(
String
executable
,
String
executable
,
List
<
String
>
arguments
,
{
List
<
String
>
arguments
,
{
Map
<
String
,
String
>
environment
,
Map
<
String
,
String
>
?
environment
,
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
String
workingDirectory
,
String
?
workingDirectory
,
StringBuffer
stderr
,
// if not null, the stderr will be written here
StringBuffer
?
stderr
,
// if not null, the stderr will be written here
bool
printStdout
=
true
,
bool
printStdout
=
true
,
bool
printStderr
=
true
,
bool
printStderr
=
true
,
})
async
{
})
async
{
...
@@ -457,10 +454,10 @@ List<String> flutterCommandArgs(String command, List<String> options) {
...
@@ -457,10 +454,10 @@ List<String> flutterCommandArgs(String command, List<String> options) {
if
(
command
==
'drive'
&&
hostAgent
.
dumpDirectory
!=
null
)
...<
String
>[
if
(
command
==
'drive'
&&
hostAgent
.
dumpDirectory
!=
null
)
...<
String
>[
'--screenshot'
,
'--screenshot'
,
hostAgent
.
dumpDirectory
.
path
,
hostAgent
.
dumpDirectory
!
.
path
,
],
],
if
(
localEngine
!=
null
)
...<
String
>[
'--local-engine'
,
localEngine
],
if
(
localEngine
!=
null
)
...<
String
>[
'--local-engine'
,
localEngine
!
],
if
(
localEngineSrcPath
!=
null
)
...<
String
>[
'--local-engine-src-path'
,
localEngineSrcPath
],
if
(
localEngineSrcPath
!=
null
)
...<
String
>[
'--local-engine-src-path'
,
localEngineSrcPath
!
],
...
options
,
...
options
,
];
];
}
}
...
@@ -470,7 +467,7 @@ List<String> flutterCommandArgs(String command, List<String> options) {
...
@@ -470,7 +467,7 @@ List<String> flutterCommandArgs(String command, List<String> options) {
Future
<
int
>
flutter
(
String
command
,
{
Future
<
int
>
flutter
(
String
command
,
{
List
<
String
>
options
=
const
<
String
>[],
List
<
String
>
options
=
const
<
String
>[],
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
Map
<
String
,
String
>
environment
=
const
<
String
,
String
>{}
,
Map
<
String
,
String
>
?
environment
,
})
{
})
{
final
List
<
String
>
args
=
flutterCommandArgs
(
command
,
options
);
final
List
<
String
>
args
=
flutterCommandArgs
(
command
,
options
);
return
exec
(
path
.
join
(
flutterDirectory
.
path
,
'bin'
,
'flutter'
),
args
,
return
exec
(
path
.
join
(
flutterDirectory
.
path
,
'bin'
,
'flutter'
),
args
,
...
@@ -493,8 +490,8 @@ Future<Process> startFlutter(String command, {
...
@@ -493,8 +490,8 @@ Future<Process> startFlutter(String command, {
Future
<
String
>
evalFlutter
(
String
command
,
{
Future
<
String
>
evalFlutter
(
String
command
,
{
List
<
String
>
options
=
const
<
String
>[],
List
<
String
>
options
=
const
<
String
>[],
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
Map
<
String
,
String
>
environment
,
Map
<
String
,
String
>
?
environment
,
StringBuffer
stderr
,
// if not null, the stderr will be written here.
StringBuffer
?
stderr
,
// if not null, the stderr will be written here.
})
{
})
{
final
List
<
String
>
args
=
flutterCommandArgs
(
command
,
options
);
final
List
<
String
>
args
=
flutterCommandArgs
(
command
,
options
);
return
eval
(
path
.
join
(
flutterDirectory
.
path
,
'bin'
,
'flutter'
),
args
,
return
eval
(
path
.
join
(
flutterDirectory
.
path
,
'bin'
,
'flutter'
),
args
,
...
@@ -521,7 +518,7 @@ Future<int> dart(List<String> args) => exec(dartBin, <String>['--disable-dart-de
...
@@ -521,7 +518,7 @@ Future<int> dart(List<String> args) => exec(dartBin, <String>['--disable-dart-de
/// Returns a future that completes with a path suitable for JAVA_HOME
/// Returns a future that completes with a path suitable for JAVA_HOME
/// or with null, if Java cannot be found.
/// or with null, if Java cannot be found.
Future
<
String
>
findJavaHome
()
async
{
Future
<
String
?
>
findJavaHome
()
async
{
if
(
_javaHome
==
null
)
{
if
(
_javaHome
==
null
)
{
final
Iterable
<
String
>
hits
=
grep
(
final
Iterable
<
String
>
hits
=
grep
(
'Java binary at: '
,
'Java binary at: '
,
...
@@ -537,7 +534,7 @@ Future<String> findJavaHome() async {
...
@@ -537,7 +534,7 @@ Future<String> findJavaHome() async {
}
}
return
_javaHome
;
return
_javaHome
;
}
}
String
_javaHome
;
String
?
_javaHome
;
Future
<
T
>
inDirectory
<
T
>(
dynamic
directory
,
Future
<
T
>
Function
()
action
)
async
{
Future
<
T
>
inDirectory
<
T
>(
dynamic
directory
,
Future
<
T
>
Function
()
action
)
async
{
final
String
previousCwd
=
cwd
;
final
String
previousCwd
=
cwd
;
...
@@ -568,12 +565,12 @@ void cd(dynamic directory) {
...
@@ -568,12 +565,12 @@ void cd(dynamic directory) {
Directory
get
flutterDirectory
=>
Directory
.
current
.
parent
.
parent
;
Directory
get
flutterDirectory
=>
Directory
.
current
.
parent
.
parent
;
String
requireEnvVar
(
String
name
)
{
String
requireEnvVar
(
String
name
)
{
final
String
value
=
Platform
.
environment
[
name
];
final
String
?
value
=
Platform
.
environment
[
name
];
if
(
value
==
null
)
if
(
value
==
null
)
fail
(
'
$name
environment variable is missing. Quitting.'
);
fail
(
'
$name
environment variable is missing. Quitting.'
);
return
value
;
return
value
!
;
}
}
T
requireConfigProperty
<
T
>(
Map
<
String
,
dynamic
>
map
,
String
propertyName
)
{
T
requireConfigProperty
<
T
>(
Map
<
String
,
dynamic
>
map
,
String
propertyName
)
{
...
@@ -637,7 +634,7 @@ void checkNotNull(Object o1,
...
@@ -637,7 +634,7 @@ void checkNotNull(Object o1,
}
}
/// Splits [from] into lines and selects those that contain [pattern].
/// Splits [from] into lines and selects those that contain [pattern].
Iterable
<
String
>
grep
(
Pattern
pattern
,
{
@
required
String
from
})
{
Iterable
<
String
>
grep
(
Pattern
pattern
,
{
required
String
from
})
{
return
from
.
split
(
'
\n
'
).
where
((
String
line
)
{
return
from
.
split
(
'
\n
'
).
where
((
String
line
)
{
return
line
.
contains
(
pattern
);
return
line
.
contains
(
pattern
);
});
});
...
@@ -675,8 +672,8 @@ final RegExp _obsUriRegExp = RegExp(r'((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)');
...
@@ -675,8 +672,8 @@ final RegExp _obsUriRegExp = RegExp(r'((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)');
///
///
/// The `prefix`, if specified, is a regular expression pattern and must not contain groups.
/// The `prefix`, if specified, is a regular expression pattern and must not contain groups.
/// `prefix` defaults to the RegExp: `An Observatory debugger .* is available at: `.
/// `prefix` defaults to the RegExp: `An Observatory debugger .* is available at: `.
int
parseServicePort
(
String
line
,
{
int
?
parseServicePort
(
String
line
,
{
Pattern
prefix
,
Pattern
?
prefix
,
})
{
})
{
prefix
??=
_obsRegExp
;
prefix
??=
_obsRegExp
;
final
Iterable
<
Match
>
matchesIter
=
prefix
.
allMatches
(
line
);
final
Iterable
<
Match
>
matchesIter
=
prefix
.
allMatches
(
line
);
...
@@ -686,15 +683,15 @@ int parseServicePort(String line, {
...
@@ -686,15 +683,15 @@ int parseServicePort(String line, {
final
Match
prefixMatch
=
matchesIter
.
first
;
final
Match
prefixMatch
=
matchesIter
.
first
;
final
List
<
Match
>
matches
=
final
List
<
Match
>
matches
=
_obsPortRegExp
.
allMatches
(
line
,
prefixMatch
.
end
).
toList
();
_obsPortRegExp
.
allMatches
(
line
,
prefixMatch
.
end
).
toList
();
return
matches
.
isEmpty
?
null
:
int
.
parse
(
matches
[
0
].
group
(
2
));
return
matches
.
isEmpty
?
null
:
int
.
parse
(
matches
[
0
].
group
(
2
)
!
);
}
}
/// Tries to extract a URL from the string.
/// Tries to extract a URL from the string.
///
///
/// The `prefix`, if specified, is a regular expression pattern and must not contain groups.
/// The `prefix`, if specified, is a regular expression pattern and must not contain groups.
/// `prefix` defaults to the RegExp: `An Observatory debugger .* is available at: `.
/// `prefix` defaults to the RegExp: `An Observatory debugger .* is available at: `.
Uri
parseServiceUri
(
String
line
,
{
Uri
?
parseServiceUri
(
String
line
,
{
Pattern
prefix
,
Pattern
?
prefix
,
})
{
})
{
prefix
??=
_obsRegExp
;
prefix
??=
_obsRegExp
;
final
Iterable
<
Match
>
matchesIter
=
prefix
.
allMatches
(
line
);
final
Iterable
<
Match
>
matchesIter
=
prefix
.
allMatches
(
line
);
...
@@ -704,7 +701,7 @@ Uri parseServiceUri(String line, {
...
@@ -704,7 +701,7 @@ Uri parseServiceUri(String line, {
final
Match
prefixMatch
=
matchesIter
.
first
;
final
Match
prefixMatch
=
matchesIter
.
first
;
final
List
<
Match
>
matches
=
final
List
<
Match
>
matches
=
_obsUriRegExp
.
allMatches
(
line
,
prefixMatch
.
end
).
toList
();
_obsUriRegExp
.
allMatches
(
line
,
prefixMatch
.
end
).
toList
();
return
matches
.
isEmpty
?
null
:
Uri
.
parse
(
matches
[
0
].
group
(
0
));
return
matches
.
isEmpty
?
null
:
Uri
.
parse
(
matches
[
0
].
group
(
0
)
!
);
}
}
/// Checks that the file exists, otherwise throws a [FileSystemException].
/// Checks that the file exists, otherwise throws a [FileSystemException].
...
@@ -771,7 +768,7 @@ void checkFileContains(List<Pattern> patterns, String filePath) {
...
@@ -771,7 +768,7 @@ void checkFileContains(List<Pattern> patterns, String filePath) {
///
///
/// Removes the directory [path], then clones the git repository
/// Removes the directory [path], then clones the git repository
/// specified by [repo] to the directory [path].
/// specified by [repo] to the directory [path].
Future
<
int
>
gitClone
({
String
path
,
String
repo
})
async
{
Future
<
int
>
gitClone
({
required
String
path
,
required
String
repo
})
async
{
rmTree
(
Directory
(
path
));
rmTree
(
Directory
(
path
));
await
Directory
(
path
).
create
(
recursive:
true
);
await
Directory
(
path
).
create
(
recursive:
true
);
...
@@ -792,7 +789,7 @@ Future<int> gitClone({String path, String repo}) async {
...
@@ -792,7 +789,7 @@ Future<int> gitClone({String path, String repo}) async {
/// Waits a constant duration of [delayDuration] between every retry attempt.
/// Waits a constant duration of [delayDuration] between every retry attempt.
Future
<
T
>
retry
<
T
>(
Future
<
T
>
retry
<
T
>(
FutureOr
<
T
>
Function
()
fn
,
{
FutureOr
<
T
>
Function
()
fn
,
{
FutureOr
<
bool
>
Function
(
Exception
)
retryIf
,
FutureOr
<
bool
>
Function
(
Exception
)
?
retryIf
,
int
maxAttempts
=
5
,
int
maxAttempts
=
5
,
Duration
delayDuration
=
const
Duration
(
seconds:
3
),
Duration
delayDuration
=
const
Duration
(
seconds:
3
),
})
async
{
})
async
{
...
...
dev/devicelab/lib/microbenchmarks.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:io'
;
...
...
dev/devicelab/lib/tasks/analysis.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
;
import
'dart:io'
;
import
'package:path/path.dart'
as
path
;
import
'package:path/path.dart'
as
path
;
...
...
dev/devicelab/lib/tasks/build_test_task.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
;
import
'dart:io'
;
import
'package:args/args.dart'
;
import
'package:args/args.dart'
;
...
@@ -18,10 +16,9 @@ import '../framework/utils.dart';
...
@@ -18,10 +16,9 @@ import '../framework/utils.dart';
abstract
class
BuildTestTask
{
abstract
class
BuildTestTask
{
BuildTestTask
(
this
.
args
,
{
this
.
workingDirectory
,
this
.
runFlutterClean
=
true
,})
{
BuildTestTask
(
this
.
args
,
{
this
.
workingDirectory
,
this
.
runFlutterClean
=
true
,})
{
final
ArgResults
argResults
=
argParser
.
parse
(
args
);
final
ArgResults
argResults
=
argParser
.
parse
(
args
);
applicationBinaryPath
=
argResults
[
kApplicationBinaryPathOption
]
as
String
;
applicationBinaryPath
=
argResults
[
kApplicationBinaryPathOption
]
as
String
?
;
buildOnly
=
argResults
[
kBuildOnlyFlag
]
as
bool
;
buildOnly
=
argResults
[
kBuildOnlyFlag
]
as
bool
;
testOnly
=
argResults
[
kTestOnlyFlag
]
as
bool
;
testOnly
=
argResults
[
kTestOnlyFlag
]
as
bool
;
}
}
static
const
String
kApplicationBinaryPathOption
=
'application-binary-path'
;
static
const
String
kApplicationBinaryPathOption
=
'application-binary-path'
;
...
@@ -48,10 +45,10 @@ abstract class BuildTestTask {
...
@@ -48,10 +45,10 @@ abstract class BuildTestTask {
/// Path to a built application to use in [test].
/// Path to a built application to use in [test].
///
///
/// If not given, will default to child's expected location.
/// If not given, will default to child's expected location.
String
applicationBinaryPath
;
String
?
applicationBinaryPath
;
/// Where the test artifacts are stored, such as performance results.
/// Where the test artifacts are stored, such as performance results.
final
Directory
workingDirectory
;
final
Directory
?
workingDirectory
;
/// Run Flutter build to create [applicationBinaryPath].
/// Run Flutter build to create [applicationBinaryPath].
Future
<
void
>
build
()
async
{
Future
<
void
>
build
()
async
{
...
@@ -93,7 +90,7 @@ abstract class BuildTestTask {
...
@@ -93,7 +90,7 @@ abstract class BuildTestTask {
///
///
/// Tasks can override to support default values. Otherwise, it will default
/// Tasks can override to support default values. Otherwise, it will default
/// to needing to be passed as an argument in the test runner.
/// to needing to be passed as an argument in the test runner.
String
getApplicationBinaryPath
()
=>
applicationBinaryPath
;
String
?
getApplicationBinaryPath
()
=>
applicationBinaryPath
;
/// Run this task.
/// Run this task.
///
///
...
...
dev/devicelab/lib/tasks/dart_plugin_registry_tests.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:io'
;
...
@@ -15,8 +13,8 @@ import 'package:flutter_devicelab/framework/utils.dart';
...
@@ -15,8 +13,8 @@ import 'package:flutter_devicelab/framework/utils.dart';
import
'package:path/path.dart'
as
path
;
import
'package:path/path.dart'
as
path
;
TaskFunction
dartPluginRegistryTest
(
{
TaskFunction
dartPluginRegistryTest
(
{
String
deviceIdOverride
,
String
?
deviceIdOverride
,
Map
<
String
,
String
>
environment
,
Map
<
String
,
String
>
?
environment
,
})
{
})
{
final
Directory
tempDir
=
Directory
.
systemTemp
final
Directory
tempDir
=
Directory
.
systemTemp
.
createTempSync
(
'flutter_devicelab_dart_plugin_test.'
);
.
createTempSync
(
'flutter_devicelab_dart_plugin_test.'
);
...
...
dev/devicelab/lib/tasks/gallery.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:io'
;
import
'dart:math'
as
math
;
import
'dart:math'
as
math
;
...
@@ -55,9 +53,9 @@ class GalleryTransitionTest {
...
@@ -55,9 +53,9 @@ class GalleryTransitionTest {
final
bool
needFullTimeline
;
final
bool
needFullTimeline
;
final
String
testFile
;
final
String
testFile
;
final
String
timelineSummaryFile
;
final
String
timelineSummaryFile
;
final
String
timelineTraceFile
;
final
String
?
timelineTraceFile
;
final
String
transitionDurationFile
;
final
String
?
transitionDurationFile
;
final
String
driverFile
;
final
String
?
driverFile
;
Future
<
TaskResult
>
call
()
async
{
Future
<
TaskResult
>
call
()
async
{
final
Device
device
=
await
devices
.
workingDevice
;
final
Device
device
=
await
devices
.
workingDevice
;
...
@@ -65,7 +63,7 @@ class GalleryTransitionTest {
...
@@ -65,7 +63,7 @@ class GalleryTransitionTest {
final
String
deviceId
=
device
.
deviceId
;
final
String
deviceId
=
device
.
deviceId
;
final
Directory
galleryDirectory
=
dir
(
'
${flutterDirectory.path}
/dev/integration_tests/flutter_gallery'
);
final
Directory
galleryDirectory
=
dir
(
'
${flutterDirectory.path}
/dev/integration_tests/flutter_gallery'
);
await
inDirectory
<
void
>(
galleryDirectory
,
()
async
{
await
inDirectory
<
void
>(
galleryDirectory
,
()
async
{
String
applicationBinaryPath
;
String
?
applicationBinaryPath
;
if
(
deviceOperatingSystem
==
DeviceOperatingSystem
.
android
)
{
if
(
deviceOperatingSystem
==
DeviceOperatingSystem
.
android
)
{
section
(
'BUILDING APPLICATION'
);
section
(
'BUILDING APPLICATION'
);
await
flutter
(
await
flutter
(
...
...
dev/devicelab/lib/tasks/hot_mode_tests.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:io'
;
...
@@ -20,7 +18,7 @@ final Directory flutterGalleryDir = dir(path.join(flutterDirectory.path, 'dev/in
...
@@ -20,7 +18,7 @@ final Directory flutterGalleryDir = dir(path.join(flutterDirectory.path, 'dev/in
const
String
kSourceLine
=
'fontSize: (orientation == Orientation.portrait) ? 32.0 : 24.0'
;
const
String
kSourceLine
=
'fontSize: (orientation == Orientation.portrait) ? 32.0 : 24.0'
;
const
String
kReplacementLine
=
'fontSize: (orientation == Orientation.portrait) ? 34.0 : 24.0'
;
const
String
kReplacementLine
=
'fontSize: (orientation == Orientation.portrait) ? 34.0 : 24.0'
;
TaskFunction
createHotModeTest
(
{
String
deviceIdOverride
,
Map
<
String
,
String
>
environment
})
{
TaskFunction
createHotModeTest
(
{
String
?
deviceIdOverride
,
Map
<
String
,
String
>?
environment
})
{
// This file is modified during the test and needs to be restored at the end.
// This file is modified during the test and needs to be restored at the end.
final
File
flutterFrameworkSource
=
file
(
path
.
join
(
final
File
flutterFrameworkSource
=
file
(
path
.
join
(
flutterDirectory
.
path
,
'packages/flutter/lib/src/widgets/framework.dart'
,
flutterDirectory
.
path
,
'packages/flutter/lib/src/widgets/framework.dart'
,
...
@@ -35,13 +33,13 @@ TaskFunction createHotModeTest({String deviceIdOverride, Map<String, String> env
...
@@ -35,13 +33,13 @@ TaskFunction createHotModeTest({String deviceIdOverride, Map<String, String> env
final
File
benchmarkFile
=
file
(
path
.
join
(
_editedFlutterGalleryDir
.
path
,
'hot_benchmark.json'
));
final
File
benchmarkFile
=
file
(
path
.
join
(
_editedFlutterGalleryDir
.
path
,
'hot_benchmark.json'
));
rm
(
benchmarkFile
);
rm
(
benchmarkFile
);
final
List
<
String
>
options
=
<
String
>[
final
List
<
String
>
options
=
<
String
>[
'--hot'
,
'-d'
,
deviceIdOverride
,
'--benchmark'
,
'--resident'
,
'--no-android-gradle-daemon'
,
'--no-publish-port'
,
'--verbose'
,
'--hot'
,
'-d'
,
deviceIdOverride
!
,
'--benchmark'
,
'--resident'
,
'--no-android-gradle-daemon'
,
'--no-publish-port'
,
'--verbose'
,
];
];
int
hotReloadCount
=
0
;
int
hotReloadCount
=
0
;
Map
<
String
,
dynamic
>
smallReloadData
;
late
Map
<
String
,
dynamic
>
smallReloadData
;
Map
<
String
,
dynamic
>
mediumReloadData
;
late
Map
<
String
,
dynamic
>
mediumReloadData
;
Map
<
String
,
dynamic
>
largeReloadData
;
late
Map
<
String
,
dynamic
>
largeReloadData
;
Map
<
String
,
dynamic
>
freshRestartReloadsData
;
late
Map
<
String
,
dynamic
>
freshRestartReloadsData
;
await
inDirectory
<
void
>(
flutterDirectory
,
()
async
{
await
inDirectory
<
void
>(
flutterDirectory
,
()
async
{
...
@@ -215,9 +213,9 @@ TaskFunction createHotModeTest({String deviceIdOverride, Map<String, String> env
...
@@ -215,9 +213,9 @@ TaskFunction createHotModeTest({String deviceIdOverride, Map<String, String> env
};
};
}
}
Future
<
Map
<
String
,
Object
>>
captureReloadData
(
Future
<
Map
<
String
,
dynamic
>>
captureReloadData
(
List
<
String
>
options
,
List
<
String
>
options
,
Map
<
String
,
String
>
environment
,
Map
<
String
,
String
>
?
environment
,
File
benchmarkFile
,
File
benchmarkFile
,
void
Function
(
String
,
Process
)
onLine
,
void
Function
(
String
,
Process
)
onLine
,
)
async
{
)
async
{
...
@@ -247,7 +245,7 @@ Future<Map<String, Object>> captureReloadData(
...
@@ -247,7 +245,7 @@ Future<Map<String, Object>> captureReloadData(
await
Future
.
wait
<
void
>(<
Future
<
void
>>[
stdoutDone
.
future
,
stderrDone
.
future
]);
await
Future
.
wait
<
void
>(<
Future
<
void
>>[
stdoutDone
.
future
,
stderrDone
.
future
]);
await
process
.
exitCode
;
await
process
.
exitCode
;
final
Map
<
String
,
dynamic
>
result
=
json
.
decode
(
benchmarkFile
.
readAsStringSync
())
as
Map
<
String
,
dynamic
>;
final
Map
<
String
,
Object
>
result
=
json
.
decode
(
benchmarkFile
.
readAsStringSync
())
as
Map
<
String
,
Object
>;
benchmarkFile
.
deleteSync
();
benchmarkFile
.
deleteSync
();
return
result
;
return
result
;
}
}
dev/devicelab/lib/tasks/integration_tests.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'../framework/devices.dart'
;
import
'../framework/devices.dart'
;
import
'../framework/framework.dart'
;
import
'../framework/framework.dart'
;
import
'../framework/task_result.dart'
;
import
'../framework/task_result.dart'
;
...
...
dev/devicelab/lib/tasks/microbenchmarks.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:io'
;
import
'dart:io'
;
...
...
dev/devicelab/lib/tasks/new_gallery.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
;
import
'dart:io'
;
import
'package:flutter_devicelab/tasks/perf_tests.dart'
;
import
'package:flutter_devicelab/tasks/perf_tests.dart'
;
...
...
dev/devicelab/lib/tasks/perf_tests.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
show
LineSplitter
,
json
,
utf8
;
import
'dart:convert'
show
LineSplitter
,
json
,
utf8
;
import
'dart:io'
;
import
'dart:io'
;
...
@@ -516,7 +514,7 @@ class StartupTest {
...
@@ -516,7 +514,7 @@ class StartupTest {
final
List
<
Map
<
String
,
dynamic
>>
results
=
<
Map
<
String
,
dynamic
>>[];
final
List
<
Map
<
String
,
dynamic
>>
results
=
<
Map
<
String
,
dynamic
>>[];
section
(
'Building application'
);
section
(
'Building application'
);
String
applicationBinaryPath
;
String
?
applicationBinaryPath
;
switch
(
deviceOperatingSystem
)
{
switch
(
deviceOperatingSystem
)
{
case
DeviceOperatingSystem
.
android
:
case
DeviceOperatingSystem
.
android
:
await
flutter
(
'build'
,
options:
<
String
>[
await
flutter
(
'build'
,
options:
<
String
>[
...
@@ -586,7 +584,7 @@ class StartupTest {
...
@@ -586,7 +584,7 @@ class StartupTest {
'-d'
,
'-d'
,
device
.
deviceId
,
device
.
deviceId
,
'--out'
,
'--out'
,
hostAgent
.
dumpDirectory
hostAgent
.
dumpDirectory
!
.
childFile
(
'screenshot_startup_failure_
$currentFailures
.png'
)
.
childFile
(
'screenshot_startup_failure_
$currentFailures
.png'
)
.
path
,
.
path
,
],
],
...
@@ -630,7 +628,7 @@ class DevtoolsStartupTest {
...
@@ -630,7 +628,7 @@ class DevtoolsStartupTest {
final
Device
device
=
await
devices
.
workingDevice
;
final
Device
device
=
await
devices
.
workingDevice
;
section
(
'Building application'
);
section
(
'Building application'
);
String
applicationBinaryPath
;
String
?
applicationBinaryPath
;
switch
(
deviceOperatingSystem
)
{
switch
(
deviceOperatingSystem
)
{
case
DeviceOperatingSystem
.
android
:
case
DeviceOperatingSystem
.
android
:
await
flutter
(
'build'
,
options:
<
String
>[
await
flutter
(
'build'
,
options:
<
String
>[
...
@@ -733,7 +731,7 @@ class PerfTest {
...
@@ -733,7 +731,7 @@ class PerfTest {
this
.
needsFullTimeline
=
true
,
this
.
needsFullTimeline
=
true
,
this
.
benchmarkScoreKeys
,
this
.
benchmarkScoreKeys
,
this
.
dartDefine
=
''
,
this
.
dartDefine
=
''
,
String
resultFilename
,
String
?
resultFilename
,
}):
_resultFilename
=
resultFilename
;
}):
_resultFilename
=
resultFilename
;
const
PerfTest
.
e2e
(
const
PerfTest
.
e2e
(
...
@@ -753,12 +751,12 @@ class PerfTest {
...
@@ -753,12 +751,12 @@ class PerfTest {
/// The main entry-point file of the application, as run on the device.
/// The main entry-point file of the application, as run on the device.
final
String
testTarget
;
final
String
testTarget
;
// The prefix name of the filename such as `<timelineFileName>.timeline_summary.json`.
// The prefix name of the filename such as `<timelineFileName>.timeline_summary.json`.
final
String
timelineFileName
;
final
String
?
timelineFileName
;
String
get
traceFilename
=>
'
$timelineFileName
.timeline'
;
String
get
traceFilename
=>
'
$timelineFileName
.timeline'
;
String
get
resultFilename
=>
_resultFilename
??
'
$timelineFileName
.timeline_summary'
;
String
get
resultFilename
=>
_resultFilename
??
'
$timelineFileName
.timeline_summary'
;
final
String
_resultFilename
;
final
String
?
_resultFilename
;
/// The test file to run on the host.
/// The test file to run on the host.
final
String
testDriver
;
final
String
?
testDriver
;
/// Whether to collect CPU and GPU metrics.
/// Whether to collect CPU and GPU metrics.
final
bool
measureCpuGpu
;
final
bool
measureCpuGpu
;
/// Whether to collect memory metrics.
/// Whether to collect memory metrics.
...
@@ -788,7 +786,7 @@ class PerfTest {
...
@@ -788,7 +786,7 @@ class PerfTest {
/// if (measureCpuGpu) 'average_gpu_usage',
/// if (measureCpuGpu) 'average_gpu_usage',
/// ]
/// ]
/// ```
/// ```
final
List
<
String
>
benchmarkScoreKeys
;
final
List
<
String
>
?
benchmarkScoreKeys
;
/// Additional flags for `--dart-define` to control the test
/// Additional flags for `--dart-define` to control the test
final
String
dartDefine
;
final
String
dartDefine
;
...
@@ -800,8 +798,8 @@ class PerfTest {
...
@@ -800,8 +798,8 @@ class PerfTest {
@protected
@protected
Future
<
TaskResult
>
internalRun
({
Future
<
TaskResult
>
internalRun
({
bool
cacheSkSL
=
false
,
bool
cacheSkSL
=
false
,
String
existingApp
,
String
?
existingApp
,
String
writeSkslFileName
,
String
?
writeSkslFileName
,
})
{
})
{
return
inDirectory
<
TaskResult
>(
testDirectory
,
()
async
{
return
inDirectory
<
TaskResult
>(
testDirectory
,
()
async
{
final
Device
device
=
await
devices
.
workingDevice
;
final
Device
device
=
await
devices
.
workingDevice
;
...
@@ -818,7 +816,7 @@ class PerfTest {
...
@@ -818,7 +816,7 @@ class PerfTest {
'--trace-startup'
,
// Enables "endless" timeline event buffering.
'--trace-startup'
,
// Enables "endless" timeline event buffering.
'-t'
,
testTarget
,
'-t'
,
testTarget
,
if
(
testDriver
!=
null
)
if
(
testDriver
!=
null
)
...<
String
>[
'--driver'
,
testDriver
],
...<
String
>[
'--driver'
,
testDriver
!
],
if
(
existingApp
!=
null
)
if
(
existingApp
!=
null
)
...<
String
>[
'--use-existing-app'
,
existingApp
],
...<
String
>[
'--use-existing-app'
,
existingApp
],
if
(
writeSkslFileName
!=
null
)
if
(
writeSkslFileName
!=
null
)
...
@@ -890,9 +888,9 @@ class PerfTestWithSkSL extends PerfTest {
...
@@ -890,9 +888,9 @@ class PerfTestWithSkSL extends PerfTest {
String
testTarget
,
String
testTarget
,
String
timelineFileName
,
{
String
timelineFileName
,
{
bool
measureCpuGpu
=
false
,
bool
measureCpuGpu
=
false
,
String
testDriver
,
String
?
testDriver
,
bool
needsFullTimeline
=
true
,
bool
needsFullTimeline
=
true
,
List
<
String
>
benchmarkScoreKeys
,
List
<
String
>
?
benchmarkScoreKeys
,
})
:
super
(
})
:
super
(
testDirectory
,
testDirectory
,
testTarget
,
testTarget
,
...
@@ -964,7 +962,7 @@ class PerfTestWithSkSL extends PerfTest {
...
@@ -964,7 +962,7 @@ class PerfTestWithSkSL extends PerfTest {
);
);
}
}
Future
<
String
>
_runApp
({
String
appBinary
,
bool
cacheSkSL
=
false
,
String
skslPath
})
async
{
Future
<
String
>
_runApp
({
String
?
appBinary
,
bool
cacheSkSL
=
false
,
String
?
skslPath
})
async
{
if
(
File
(
_vmserviceFileName
).
existsSync
())
{
if
(
File
(
_vmserviceFileName
).
existsSync
())
{
File
(
_vmserviceFileName
).
deleteSync
();
File
(
_vmserviceFileName
).
deleteSync
();
}
}
...
@@ -1027,9 +1025,9 @@ class PerfTestWithSkSL extends PerfTest {
...
@@ -1027,9 +1025,9 @@ class PerfTestWithSkSL extends PerfTest {
});
});
}
}
String
_flutterPath
;
late
String
_flutterPath
;
Device
_device
;
late
Device
_device
;
Process
_runProcess
;
late
Process
_runProcess
;
static
const
String
_kVmserviceOutFileName
=
'vmservice.out'
;
static
const
String
_kVmserviceOutFileName
=
'vmservice.out'
;
}
}
...
@@ -1073,12 +1071,16 @@ class WebCompileTest {
...
@@ -1073,12 +1071,16 @@ class WebCompileTest {
///
///
/// Run a single web compile test for the app under [directory], and store
/// Run a single web compile test for the app under [directory], and store
/// its metrics with prefix [metric].
/// its metrics with prefix [metric].
static
Future
<
Map
<
String
,
int
>>
runSingleBuildTest
({
String
directory
,
String
metric
,
bool
measureBuildTime
=
false
})
{
static
Future
<
Map
<
String
,
int
>>
runSingleBuildTest
({
required
String
directory
,
required
String
metric
,
bool
measureBuildTime
=
false
,
})
{
return
inDirectory
<
Map
<
String
,
int
>>(
directory
,
()
async
{
return
inDirectory
<
Map
<
String
,
int
>>(
directory
,
()
async
{
final
Map
<
String
,
int
>
metrics
=
<
String
,
int
>{};
final
Map
<
String
,
int
>
metrics
=
<
String
,
int
>{};
await
flutter
(
'packages'
,
options:
<
String
>[
'get'
]);
await
flutter
(
'packages'
,
options:
<
String
>[
'get'
]);
final
Stopwatch
watch
=
measureBuildTime
?
Stopwatch
()
:
null
;
final
Stopwatch
?
watch
=
measureBuildTime
?
Stopwatch
()
:
null
;
watch
?.
start
();
watch
?.
start
();
await
evalFlutter
(
'build'
,
options:
<
String
>[
await
evalFlutter
(
'build'
,
options:
<
String
>[
'web'
,
'web'
,
...
@@ -1091,7 +1093,7 @@ class WebCompileTest {
...
@@ -1091,7 +1093,7 @@ class WebCompileTest {
metrics
.
addAll
(
await
getSize
(
outputFileName
,
metric:
metric
));
metrics
.
addAll
(
await
getSize
(
outputFileName
,
metric:
metric
));
if
(
measureBuildTime
)
{
if
(
measureBuildTime
)
{
metrics
[
'
${metric}
_dart2js_millis'
]
=
watch
.
elapsedMilliseconds
;
metrics
[
'
${metric}
_dart2js_millis'
]
=
watch
!
.
elapsedMilliseconds
;
}
}
return
metrics
;
return
metrics
;
...
@@ -1099,7 +1101,7 @@ class WebCompileTest {
...
@@ -1099,7 +1101,7 @@ class WebCompileTest {
}
}
/// Obtains the size and gzipped size of a file given by [fileName].
/// Obtains the size and gzipped size of a file given by [fileName].
static
Future
<
Map
<
String
,
int
>>
getSize
(
String
fileName
,
{
String
metric
})
async
{
static
Future
<
Map
<
String
,
int
>>
getSize
(
String
fileName
,
{
required
String
metric
})
async
{
final
Map
<
String
,
int
>
sizeMetrics
=
<
String
,
int
>{};
final
Map
<
String
,
int
>
sizeMetrics
=
<
String
,
int
>{};
final
ProcessResult
result
=
await
Process
.
run
(
'du'
,
<
String
>[
'-k'
,
fileName
]);
final
ProcessResult
result
=
await
Process
.
run
(
'du'
,
<
String
>[
'-k'
,
fileName
]);
...
@@ -1168,10 +1170,12 @@ class CompileTest {
...
@@ -1168,10 +1170,12 @@ class CompileTest {
await
flutter
(
'build'
,
options:
options
);
await
flutter
(
'build'
,
options:
options
);
watch
.
stop
();
watch
.
stop
();
final
Directory
appBuildDirectory
=
dir
(
path
.
join
(
cwd
,
'build/ios/Release-iphoneos'
));
final
Directory
appBuildDirectory
=
dir
(
path
.
join
(
cwd
,
'build/ios/Release-iphoneos'
));
final
Directory
appBundle
=
appBuildDirectory
final
Directory
?
appBundle
=
appBuildDirectory
.
listSync
()
.
listSync
()
.
whereType
<
Directory
>()
.
whereType
<
Directory
?>()
.
singleWhere
((
Directory
directory
)
=>
path
.
extension
(
directory
.
path
)
==
'.app'
,
orElse:
()
=>
null
);
.
singleWhere
((
Directory
?
directory
)
=>
directory
!=
null
&&
path
.
extension
(
directory
.
path
)
==
'.app'
,
orElse:
()
=>
null
);
if
(
appBundle
==
null
)
{
if
(
appBundle
==
null
)
{
throw
'Failed to find app bundle in
${appBuildDirectory.path}
'
;
throw
'Failed to find app bundle in
${appBuildDirectory.path}
'
;
}
}
...
@@ -1226,8 +1230,8 @@ class CompileTest {
...
@@ -1226,8 +1230,8 @@ class CompileTest {
}
}
static
Future
<
Map
<
String
,
dynamic
>>
_compileDebug
({
static
Future
<
Map
<
String
,
dynamic
>>
_compileDebug
({
@
required
bool
clean
,
required
bool
clean
,
@
required
String
metricKey
,
required
String
metricKey
,
})
async
{
})
async
{
if
(
clean
)
{
if
(
clean
)
{
await
flutter
(
'clean'
);
await
flutter
(
'clean'
);
...
@@ -1290,9 +1294,9 @@ class CompileTest {
...
@@ -1290,9 +1294,9 @@ class CompileTest {
fileToMetadata
[
entry
.
path
]
=
entry
;
fileToMetadata
[
entry
.
path
]
=
entry
;
}
}
final
_UnzipListEntry
libflutter
=
fileToMetadata
[
'lib/armeabi-v7a/libflutter.so'
];
final
_UnzipListEntry
libflutter
=
fileToMetadata
[
'lib/armeabi-v7a/libflutter.so'
]
!
;
final
_UnzipListEntry
libapp
=
fileToMetadata
[
'lib/armeabi-v7a/libapp.so'
];
final
_UnzipListEntry
libapp
=
fileToMetadata
[
'lib/armeabi-v7a/libapp.so'
]
!
;
final
_UnzipListEntry
license
=
fileToMetadata
[
'assets/flutter_assets/NOTICES.Z'
];
final
_UnzipListEntry
license
=
fileToMetadata
[
'assets/flutter_assets/NOTICES.Z'
]
!
;
return
<
String
,
dynamic
>{
return
<
String
,
dynamic
>{
'libflutter_uncompressed_bytes'
:
libflutter
.
uncompressedSize
,
'libflutter_uncompressed_bytes'
:
libflutter
.
uncompressedSize
,
...
@@ -1315,9 +1319,9 @@ class MemoryTest {
...
@@ -1315,9 +1319,9 @@ class MemoryTest {
/// Completes when the log line specified in the last call to
/// Completes when the log line specified in the last call to
/// [prepareForNextMessage] is seen by `adb logcat`.
/// [prepareForNextMessage] is seen by `adb logcat`.
Future
<
void
>
get
receivedNextMessage
=>
_receivedNextMessage
?.
future
;
Future
<
void
>
?
get
receivedNextMessage
=>
_receivedNextMessage
?.
future
;
Completer
<
void
>
_receivedNextMessage
;
Completer
<
void
>
?
_receivedNextMessage
;
String
_nextMessage
;
String
?
_nextMessage
;
/// Prepares the [receivedNextMessage] future such that it will complete
/// Prepares the [receivedNextMessage] future such that it will complete
/// when `adb logcat` sees a log line with the given `message`.
/// when `adb logcat` sees a log line with the given `message`.
...
@@ -1328,8 +1332,8 @@ class MemoryTest {
...
@@ -1328,8 +1332,8 @@ class MemoryTest {
int
get
iterationCount
=>
10
;
int
get
iterationCount
=>
10
;
Device
get
device
=>
_device
;
Device
?
get
device
=>
_device
;
Device
_device
;
Device
?
_device
;
Future
<
TaskResult
>
run
()
{
Future
<
TaskResult
>
run
()
{
return
inDirectory
<
TaskResult
>(
project
,
()
async
{
return
inDirectory
<
TaskResult
>(
project
,
()
async
{
...
@@ -1337,13 +1341,13 @@ class MemoryTest {
...
@@ -1337,13 +1341,13 @@ class MemoryTest {
// device.getMemoryStats, etc, aren't implemented for iOS.
// device.getMemoryStats, etc, aren't implemented for iOS.
_device
=
await
devices
.
workingDevice
;
_device
=
await
devices
.
workingDevice
;
await
device
.
unlock
();
await
device
!
.
unlock
();
await
flutter
(
'packages'
,
options:
<
String
>[
'get'
]);
await
flutter
(
'packages'
,
options:
<
String
>[
'get'
]);
final
StreamSubscription
<
String
>
adb
=
device
.
logcat
.
listen
(
final
StreamSubscription
<
String
>
adb
=
device
!
.
logcat
.
listen
(
(
String
data
)
{
(
String
data
)
{
if
(
data
.
contains
(
'==== MEMORY BENCHMARK ====
$_nextMessage
===='
))
if
(
data
.
contains
(
'==== MEMORY BENCHMARK ====
$_nextMessage
===='
))
_receivedNextMessage
.
complete
();
_receivedNextMessage
?
.
complete
();
},
},
);
);
...
@@ -1356,12 +1360,12 @@ class MemoryTest {
...
@@ -1356,12 +1360,12 @@ class MemoryTest {
assert
(
_endMemory
.
length
==
iteration
+
1
);
assert
(
_endMemory
.
length
==
iteration
+
1
);
assert
(
_diffMemory
.
length
==
iteration
+
1
);
assert
(
_diffMemory
.
length
==
iteration
+
1
);
print
(
'terminating...'
);
print
(
'terminating...'
);
await
device
.
stop
(
package
);
await
device
!
.
stop
(
package
);
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
10
));
await
Future
<
void
>.
delayed
(
const
Duration
(
milliseconds:
10
));
}
}
await
adb
.
cancel
();
await
adb
.
cancel
();
await
flutter
(
'install'
,
options:
<
String
>[
'--uninstall-only'
,
'-d'
,
device
.
deviceId
]);
await
flutter
(
'install'
,
options:
<
String
>[
'--uninstall-only'
,
'-d'
,
device
!
.
deviceId
]);
final
ListStatistics
startMemoryStatistics
=
ListStatistics
(
_startMemory
);
final
ListStatistics
startMemoryStatistics
=
ListStatistics
(
_startMemory
);
final
ListStatistics
endMemoryStatistics
=
ListStatistics
(
_endMemory
);
final
ListStatistics
endMemoryStatistics
=
ListStatistics
(
_endMemory
);
...
@@ -1392,7 +1396,7 @@ class MemoryTest {
...
@@ -1392,7 +1396,7 @@ class MemoryTest {
'--verbose'
,
'--verbose'
,
'--release'
,
'--release'
,
'--no-resident'
,
'--no-resident'
,
'-d'
,
device
.
deviceId
,
'-d'
,
device
!
.
deviceId
,
test
,
test
,
]);
]);
print
(
'awaiting "ready" message...'
);
print
(
'awaiting "ready" message...'
);
...
@@ -1411,7 +1415,7 @@ class MemoryTest {
...
@@ -1411,7 +1415,7 @@ class MemoryTest {
prepareForNextMessage
(
'DONE'
);
prepareForNextMessage
(
'DONE'
);
print
(
'tapping device...'
);
print
(
'tapping device...'
);
await
device
.
tap
(
100
,
100
);
await
device
!
.
tap
(
100
,
100
);
print
(
'awaiting "done" message...'
);
print
(
'awaiting "done" message...'
);
await
receivedNextMessage
;
await
receivedNextMessage
;
...
@@ -1422,23 +1426,23 @@ class MemoryTest {
...
@@ -1422,23 +1426,23 @@ class MemoryTest {
final
List
<
int
>
_endMemory
=
<
int
>[];
final
List
<
int
>
_endMemory
=
<
int
>[];
final
List
<
int
>
_diffMemory
=
<
int
>[];
final
List
<
int
>
_diffMemory
=
<
int
>[];
Map
<
String
,
dynamic
>
_startMemoryUsage
;
Map
<
String
,
dynamic
>
?
_startMemoryUsage
;
@protected
@protected
Future
<
void
>
recordStart
()
async
{
Future
<
void
>
recordStart
()
async
{
assert
(
_startMemoryUsage
==
null
);
assert
(
_startMemoryUsage
==
null
);
print
(
'snapshotting memory usage...'
);
print
(
'snapshotting memory usage...'
);
_startMemoryUsage
=
await
device
.
getMemoryStats
(
package
);
_startMemoryUsage
=
await
device
!
.
getMemoryStats
(
package
);
}
}
@protected
@protected
Future
<
void
>
recordEnd
()
async
{
Future
<
void
>
recordEnd
()
async
{
assert
(
_startMemoryUsage
!=
null
);
assert
(
_startMemoryUsage
!=
null
);
print
(
'snapshotting memory usage...'
);
print
(
'snapshotting memory usage...'
);
final
Map
<
String
,
dynamic
>
endMemoryUsage
=
await
device
.
getMemoryStats
(
package
);
final
Map
<
String
,
dynamic
>
endMemoryUsage
=
await
device
!
.
getMemoryStats
(
package
);
_startMemory
.
add
(
_startMemoryUsage
[
'total_kb'
]
as
int
);
_startMemory
.
add
(
_startMemoryUsage
!
[
'total_kb'
]
as
int
);
_endMemory
.
add
(
endMemoryUsage
[
'total_kb'
]
as
int
);
_endMemory
.
add
(
endMemoryUsage
[
'total_kb'
]
as
int
);
_diffMemory
.
add
((
endMemoryUsage
[
'total_kb'
]
as
int
)
-
(
_startMemoryUsage
[
'total_kb'
]
as
int
));
_diffMemory
.
add
((
endMemoryUsage
[
'total_kb'
]
as
int
)
-
(
_startMemoryUsage
!
[
'total_kb'
]
as
int
));
}
}
}
}
...
@@ -1487,7 +1491,7 @@ class DevToolsMemoryTest {
...
@@ -1487,7 +1491,7 @@ class DevToolsMemoryTest {
});
});
}
}
Device
_device
;
late
Device
_device
;
static
const
String
_kJsonFileName
=
'devtools_memory.json'
;
static
const
String
_kJsonFileName
=
'devtools_memory.json'
;
}
}
...
@@ -1505,7 +1509,6 @@ String _reportedDurationTestToString(ReportedDurationTestFlavor flavor) {
...
@@ -1505,7 +1509,6 @@ String _reportedDurationTestToString(ReportedDurationTestFlavor flavor) {
case
ReportedDurationTestFlavor
.
release
:
case
ReportedDurationTestFlavor
.
release
:
return
'release'
;
return
'release'
;
}
}
throw
ArgumentError
(
'Unexpected value for enum
$flavor
'
);
}
}
class
ReportedDurationTest
{
class
ReportedDurationTest
{
...
@@ -1521,8 +1524,8 @@ class ReportedDurationTest {
...
@@ -1521,8 +1524,8 @@ class ReportedDurationTest {
int
get
iterationCount
=>
10
;
int
get
iterationCount
=>
10
;
Device
get
device
=>
_device
;
Device
?
get
device
=>
_device
;
Device
_device
;
Device
?
_device
;
Future
<
TaskResult
>
run
()
{
Future
<
TaskResult
>
run
()
{
return
inDirectory
<
TaskResult
>(
project
,
()
async
{
return
inDirectory
<
TaskResult
>(
project
,
()
async
{
...
@@ -1530,13 +1533,13 @@ class ReportedDurationTest {
...
@@ -1530,13 +1533,13 @@ class ReportedDurationTest {
// device.getMemoryStats, etc, aren't implemented for iOS.
// device.getMemoryStats, etc, aren't implemented for iOS.
_device
=
await
devices
.
workingDevice
;
_device
=
await
devices
.
workingDevice
;
await
device
.
unlock
();
await
device
!
.
unlock
();
await
flutter
(
'packages'
,
options:
<
String
>[
'get'
]);
await
flutter
(
'packages'
,
options:
<
String
>[
'get'
]);
final
StreamSubscription
<
String
>
adb
=
device
.
logcat
.
listen
(
final
StreamSubscription
<
String
>
adb
=
device
!
.
logcat
.
listen
(
(
String
data
)
{
(
String
data
)
{
if
(
durationPattern
.
hasMatch
(
data
))
if
(
durationPattern
.
hasMatch
(
data
))
durationCompleter
.
complete
(
int
.
parse
(
durationPattern
.
firstMatch
(
data
)
.
group
(
1
)
));
durationCompleter
.
complete
(
int
.
parse
(
durationPattern
.
firstMatch
(
data
)
!.
group
(
1
)!
));
},
},
);
);
print
(
'launching
$project$test
on device...'
);
print
(
'launching
$project$test
on device...'
);
...
@@ -1546,13 +1549,13 @@ class ReportedDurationTest {
...
@@ -1546,13 +1549,13 @@ class ReportedDurationTest {
'--no-fast-start'
,
'--no-fast-start'
,
'--
${_reportedDurationTestToString(flavor)}
'
,
'--
${_reportedDurationTestToString(flavor)}
'
,
'--no-resident'
,
'--no-resident'
,
'-d'
,
device
.
deviceId
,
'-d'
,
device
!
.
deviceId
,
test
,
test
,
]);
]);
final
int
duration
=
await
durationCompleter
.
future
;
final
int
duration
=
await
durationCompleter
.
future
;
print
(
'terminating...'
);
print
(
'terminating...'
);
await
device
.
stop
(
package
);
await
device
!
.
stop
(
package
);
await
adb
.
cancel
();
await
adb
.
cancel
();
_device
=
null
;
_device
=
null
;
...
@@ -1607,9 +1610,9 @@ class _UnzipListEntry {
...
@@ -1607,9 +1610,9 @@ class _UnzipListEntry {
}
}
_UnzipListEntry
.
_
({
_UnzipListEntry
.
_
({
@
required
this
.
uncompressedSize
,
required
this
.
uncompressedSize
,
@
required
this
.
compressedSize
,
required
this
.
compressedSize
,
@
required
this
.
path
,
required
this
.
path
,
})
:
assert
(
uncompressedSize
!=
null
),
})
:
assert
(
uncompressedSize
!=
null
),
assert
(
compressedSize
!=
null
),
assert
(
compressedSize
!=
null
),
assert
(
compressedSize
<=
uncompressedSize
),
assert
(
compressedSize
<=
uncompressedSize
),
...
@@ -1633,7 +1636,7 @@ Future<File> waitForFile(String path) async {
...
@@ -1633,7 +1636,7 @@ Future<File> waitForFile(String path) async {
throw
StateError
(
'Did not find vmservice out file after 400 seconds'
);
throw
StateError
(
'Did not find vmservice out file after 400 seconds'
);
}
}
String
_findIosAppInBuildDirectory
(
String
searchDirectory
)
{
String
?
_findIosAppInBuildDirectory
(
String
searchDirectory
)
{
for
(
final
FileSystemEntity
entity
in
Directory
(
searchDirectory
).
listSync
())
{
for
(
final
FileSystemEntity
entity
in
Directory
(
searchDirectory
).
listSync
())
{
if
(
entity
.
path
.
endsWith
(
'.app'
))
{
if
(
entity
.
path
.
endsWith
(
'.app'
))
{
return
entity
.
path
;
return
entity
.
path
;
...
...
dev/devicelab/lib/tasks/platform_channels_benchmarks.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
show
Process
,
Directory
;
import
'dart:io'
show
Process
,
Directory
;
import
'package:flutter_devicelab/framework/devices.dart'
as
adb
;
import
'package:flutter_devicelab/framework/devices.dart'
as
adb
;
...
...
dev/devicelab/lib/tasks/plugin_tests.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:io'
;
import
'dart:io'
;
import
'package:flutter_devicelab/framework/framework.dart'
;
import
'package:flutter_devicelab/framework/framework.dart'
;
...
@@ -31,8 +29,8 @@ class PluginTest {
...
@@ -31,8 +29,8 @@ class PluginTest {
final
String
buildTarget
;
final
String
buildTarget
;
final
List
<
String
>
options
;
final
List
<
String
>
options
;
final
Map
<
String
,
String
>
pluginCreateEnvironment
;
final
Map
<
String
,
String
>
?
pluginCreateEnvironment
;
final
Map
<
String
,
String
>
appCreateEnvironment
;
final
Map
<
String
,
String
>
?
appCreateEnvironment
;
Future
<
TaskResult
>
call
()
async
{
Future
<
TaskResult
>
call
()
async
{
final
Directory
tempDir
=
final
Directory
tempDir
=
...
@@ -77,7 +75,7 @@ class _FlutterProject {
...
@@ -77,7 +75,7 @@ class _FlutterProject {
String
get
rootPath
=>
path
.
join
(
parent
.
path
,
name
);
String
get
rootPath
=>
path
.
join
(
parent
.
path
,
name
);
Future
<
void
>
addPlugin
(
String
plugin
,
{
String
pluginPath
})
async
{
Future
<
void
>
addPlugin
(
String
plugin
,
{
String
?
pluginPath
})
async
{
final
File
pubspec
=
File
(
path
.
join
(
rootPath
,
'pubspec.yaml'
));
final
File
pubspec
=
File
(
path
.
join
(
rootPath
,
'pubspec.yaml'
));
String
content
=
await
pubspec
.
readAsString
();
String
content
=
await
pubspec
.
readAsString
();
final
String
dependency
=
final
String
dependency
=
...
@@ -100,9 +98,9 @@ class _FlutterProject {
...
@@ -100,9 +98,9 @@ class _FlutterProject {
List
<
String
>
options
,
List
<
String
>
options
,
String
target
,
String
target
,
{
{
String
name
,
required
String
name
,
String
template
,
required
String
template
,
Map
<
String
,
String
>
environment
,
Map
<
String
,
String
>
?
environment
,
})
async
{
})
async
{
await
inDirectory
(
directory
,
()
async
{
await
inDirectory
(
directory
,
()
async
{
await
flutter
(
await
flutter
(
...
...
dev/devicelab/lib/tasks/web_benchmarks.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
show
json
;
import
'dart:convert'
show
json
;
import
'dart:io'
as
io
;
import
'dart:io'
as
io
;
...
@@ -13,7 +11,6 @@ import 'package:flutter_devicelab/framework/browser.dart';
...
@@ -13,7 +11,6 @@ import 'package:flutter_devicelab/framework/browser.dart';
import
'package:flutter_devicelab/framework/task_result.dart'
;
import
'package:flutter_devicelab/framework/task_result.dart'
;
import
'package:flutter_devicelab/framework/utils.dart'
;
import
'package:flutter_devicelab/framework/utils.dart'
;
import
'package:logging/logging.dart'
;
import
'package:logging/logging.dart'
;
import
'package:meta/meta.dart'
;
import
'package:path/path.dart'
as
path
;
import
'package:path/path.dart'
as
path
;
import
'package:shelf/shelf.dart'
;
import
'package:shelf/shelf.dart'
;
import
'package:shelf/shelf_io.dart'
as
shelf_io
;
import
'package:shelf/shelf_io.dart'
as
shelf_io
;
...
@@ -23,7 +20,7 @@ import 'package:shelf_static/shelf_static.dart';
...
@@ -23,7 +20,7 @@ import 'package:shelf_static/shelf_static.dart';
const
int
benchmarkServerPort
=
9999
;
const
int
benchmarkServerPort
=
9999
;
const
int
chromeDebugPort
=
10000
;
const
int
chromeDebugPort
=
10000
;
Future
<
TaskResult
>
runWebBenchmark
({
@
required
bool
useCanvasKit
})
async
{
Future
<
TaskResult
>
runWebBenchmark
({
required
bool
useCanvasKit
})
async
{
// Reduce logging level. Otherwise, package:webkit_inspection_protocol is way too spammy.
// Reduce logging level. Otherwise, package:webkit_inspection_protocol is way too spammy.
Logger
.
root
.
level
=
Level
.
INFO
;
Logger
.
root
.
level
=
Level
.
INFO
;
final
String
macrobenchmarksDirectory
=
path
.
join
(
flutterDirectory
.
path
,
'dev'
,
'benchmarks'
,
'macrobenchmarks'
);
final
String
macrobenchmarksDirectory
=
path
.
join
(
flutterDirectory
.
path
,
'dev'
,
'benchmarks'
,
'macrobenchmarks'
);
...
@@ -38,17 +35,17 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
...
@@ -38,17 +35,17 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
]);
]);
final
Completer
<
List
<
Map
<
String
,
dynamic
>>>
profileData
=
Completer
<
List
<
Map
<
String
,
dynamic
>>>();
final
Completer
<
List
<
Map
<
String
,
dynamic
>>>
profileData
=
Completer
<
List
<
Map
<
String
,
dynamic
>>>();
final
List
<
Map
<
String
,
dynamic
>>
collectedProfiles
=
<
Map
<
String
,
dynamic
>>[];
final
List
<
Map
<
String
,
dynamic
>>
collectedProfiles
=
<
Map
<
String
,
dynamic
>>[];
List
<
String
>
benchmarks
;
List
<
String
>
?
benchmarks
;
Iterator
<
String
>
benchmarkIterator
;
late
Iterator
<
String
>
benchmarkIterator
;
// This future fixes a race condition between the web-page loading and
// This future fixes a race condition between the web-page loading and
// asking to run a benchmark, and us connecting to Chrome's DevTools port.
// asking to run a benchmark, and us connecting to Chrome's DevTools port.
// Sometime one wins. Other times, the other wins.
// Sometime one wins. Other times, the other wins.
Future
<
Chrome
>
whenChromeIsReady
;
Future
<
Chrome
>
?
whenChromeIsReady
;
Chrome
chrome
;
Chrome
?
chrome
;
io
.
HttpServer
server
;
late
io
.
HttpServer
server
;
Cascade
cascade
=
Cascade
();
Cascade
cascade
=
Cascade
();
List
<
Map
<
String
,
dynamic
>>
latestPerformanceTrace
;
List
<
Map
<
String
,
dynamic
>>
?
latestPerformanceTrace
;
cascade
=
cascade
.
add
((
Request
request
)
async
{
cascade
=
cascade
.
add
((
Request
request
)
async
{
try
{
try
{
chrome
??=
await
whenChromeIsReady
;
chrome
??=
await
whenChromeIsReady
;
...
@@ -66,7 +63,7 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
...
@@ -66,7 +63,7 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
// Trace data is null when the benchmark is not frame-based, such as RawRecorder.
// Trace data is null when the benchmark is not frame-based, such as RawRecorder.
if
(
latestPerformanceTrace
!=
null
)
{
if
(
latestPerformanceTrace
!=
null
)
{
final
BlinkTraceSummary
traceSummary
=
BlinkTraceSummary
.
fromJson
(
latestPerformanceTrace
)
;
final
BlinkTraceSummary
traceSummary
=
BlinkTraceSummary
.
fromJson
(
latestPerformanceTrace
!)!
;
profile
[
'totalUiFrame.average'
]
=
traceSummary
.
averageTotalUIFrameTime
.
inMicroseconds
;
profile
[
'totalUiFrame.average'
]
=
traceSummary
.
averageTotalUIFrameTime
.
inMicroseconds
;
profile
[
'scoreKeys'
]
??=
<
dynamic
>[];
// using dynamic for consistency with JSON
profile
[
'scoreKeys'
]
??=
<
dynamic
>[];
// using dynamic for consistency with JSON
(
profile
[
'scoreKeys'
]
as
List
<
dynamic
>).
add
(
'totalUiFrame.average'
);
(
profile
[
'scoreKeys'
]
as
List
<
dynamic
>).
add
(
'totalUiFrame.average'
);
...
@@ -76,10 +73,10 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
...
@@ -76,10 +73,10 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
return
Response
.
ok
(
'Profile received'
);
return
Response
.
ok
(
'Profile received'
);
}
else
if
(
request
.
requestedUri
.
path
.
endsWith
(
'/start-performance-tracing'
))
{
}
else
if
(
request
.
requestedUri
.
path
.
endsWith
(
'/start-performance-tracing'
))
{
latestPerformanceTrace
=
null
;
latestPerformanceTrace
=
null
;
await
chrome
.
beginRecordingPerformance
(
request
.
requestedUri
.
queryParameters
[
'label'
]
);
await
chrome
!.
beginRecordingPerformance
(
request
.
requestedUri
.
queryParameters
[
'label'
]!
);
return
Response
.
ok
(
'Started performance tracing'
);
return
Response
.
ok
(
'Started performance tracing'
);
}
else
if
(
request
.
requestedUri
.
path
.
endsWith
(
'/stop-performance-tracing'
))
{
}
else
if
(
request
.
requestedUri
.
path
.
endsWith
(
'/stop-performance-tracing'
))
{
latestPerformanceTrace
=
await
chrome
.
endRecordingPerformance
();
latestPerformanceTrace
=
await
chrome
!
.
endRecordingPerformance
();
return
Response
.
ok
(
'Stopped performance tracing'
);
return
Response
.
ok
(
'Stopped performance tracing'
);
}
else
if
(
request
.
requestedUri
.
path
.
endsWith
(
'/on-error'
))
{
}
else
if
(
request
.
requestedUri
.
path
.
endsWith
(
'/on-error'
))
{
final
Map
<
String
,
dynamic
>
errorDetails
=
json
.
decode
(
await
request
.
readAsString
())
as
Map
<
String
,
dynamic
>;
final
Map
<
String
,
dynamic
>
errorDetails
=
json
.
decode
(
await
request
.
readAsString
())
as
Map
<
String
,
dynamic
>;
...
@@ -90,7 +87,7 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
...
@@ -90,7 +87,7 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
}
else
if
(
request
.
requestedUri
.
path
.
endsWith
(
'/next-benchmark'
))
{
}
else
if
(
request
.
requestedUri
.
path
.
endsWith
(
'/next-benchmark'
))
{
if
(
benchmarks
==
null
)
{
if
(
benchmarks
==
null
)
{
benchmarks
=
(
json
.
decode
(
await
request
.
readAsString
())
as
List
<
dynamic
>).
cast
<
String
>();
benchmarks
=
(
json
.
decode
(
await
request
.
readAsString
())
as
List
<
dynamic
>).
cast
<
String
>();
benchmarkIterator
=
benchmarks
.
iterator
;
benchmarkIterator
=
benchmarks
!
.
iterator
;
}
}
if
(
benchmarkIterator
.
moveNext
())
{
if
(
benchmarkIterator
.
moveNext
())
{
final
String
nextBenchmark
=
benchmarkIterator
.
current
;
final
String
nextBenchmark
=
benchmarkIterator
.
current
;
...
@@ -186,7 +183,7 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
...
@@ -186,7 +183,7 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
}
}
return
TaskResult
.
success
(
taskResult
,
benchmarkScoreKeys:
benchmarkScoreKeys
);
return
TaskResult
.
success
(
taskResult
,
benchmarkScoreKeys:
benchmarkScoreKeys
);
}
finally
{
}
finally
{
unawaited
(
server
?
.
close
());
unawaited
(
server
.
close
());
chrome
?.
stop
();
chrome
?.
stop
();
}
}
});
});
...
...
dev/devicelab/lib/tasks/web_dev_mode_tests.dart
View file @
ef5ffd08
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
// @dart = 2.8
import
'dart:async'
;
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:io'
;
...
...
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