4
4
5
5
import 'dart:async' ;
6
6
import 'dart:convert' ;
7
+ // import 'dart:core' as core;
7
8
import 'dart:io' ;
8
9
9
10
import 'package:flutter_devicelab/common.dart' ;
@@ -15,6 +16,16 @@ import 'devices.dart';
15
16
import 'task_result.dart' ;
16
17
import 'utils.dart' ;
17
18
19
+ /// Run a list of tasks.
20
+ ///
21
+ /// For each task, an auto rerun will be triggered when task fails.
22
+ ///
23
+ /// If the task succeeds the first time, it will be recorded as successful.
24
+ ///
25
+ /// If the task fails first, but gets passed in the end, the
26
+ /// test will be recorded as successful but with a flake flag.
27
+ ///
28
+ /// If the task fails all reruns, it will be recorded as failed.
18
29
Future <void > runTasks (
19
30
List <String > taskNames, {
20
31
bool exitOnFirstTestFailure = false ,
@@ -26,33 +37,45 @@ Future<void> runTasks(
26
37
String ? luciBuilder,
27
38
String ? resultsPath,
28
39
List <String >? taskArgs,
40
+ @visibleForTesting Map <String , String >? isolateParams,
41
+ @visibleForTesting Function (String ) print = print,
42
+ @visibleForTesting List <String >? logs,
29
43
}) async {
30
44
for (final String taskName in taskNames) {
31
- section ('Running task "$taskName "' );
32
- final TaskResult result = await runTask (
33
- taskName,
34
- deviceId: deviceId,
35
- localEngine: localEngine,
36
- localEngineSrcPath: localEngineSrcPath,
37
- silent: silent,
38
- taskArgs: taskArgs,
39
- );
40
-
41
- print ('Task result:' );
42
- print (const JsonEncoder .withIndent (' ' ).convert (result));
43
- section ('Finished task "$taskName "' );
44
-
45
- if (resultsPath != null ) {
46
- final Cocoon cocoon = Cocoon ();
47
- await cocoon.writeTaskResultToFile (
48
- builderName: luciBuilder,
49
- gitBranch: gitBranch,
50
- result: result,
45
+ TaskResult result = TaskResult .success (null );
46
+ int retry = 0 ;
47
+ while (retry <= Cocoon .retryNumber) {
48
+ result = await rerunTask (
49
+ taskName,
50
+ deviceId: deviceId,
51
+ localEngine: localEngine,
52
+ localEngineSrcPath: localEngineSrcPath,
53
+ silent: silent,
54
+ taskArgs: taskArgs,
51
55
resultsPath: resultsPath,
56
+ gitBranch: gitBranch,
57
+ luciBuilder: luciBuilder,
58
+ isolateParams: isolateParams,
52
59
);
60
+
61
+ section ('Flaky status for "$taskName "' );
62
+ if (! result.succeeded) {
63
+ retry++ ;
64
+ } else {
65
+ if (retry > 0 ) {
66
+ print ('Total ${retry +1 } executions: $retry failures and 1 success' );
67
+ print ('flaky: true' );
68
+ } else {
69
+ print ('Total ${retry +1 } executions: 1 success' );
70
+ print ('flaky: false' );
71
+ }
72
+ break ;
73
+ }
53
74
}
54
75
55
76
if (! result.succeeded) {
77
+ print ('Total $retry executions: 0 success' );
78
+ print ('flaky: false' );
56
79
exitCode = 1 ;
57
80
if (exitOnFirstTestFailure) {
58
81
return ;
@@ -61,6 +84,48 @@ Future<void> runTasks(
61
84
}
62
85
}
63
86
87
+ /// A rerun wrapper for `runTask` .
88
+ ///
89
+ /// This separates reruns in separate sections.
90
+ Future <TaskResult > rerunTask (
91
+ String taskName, {
92
+ String ? deviceId,
93
+ String ? localEngine,
94
+ String ? localEngineSrcPath,
95
+ bool silent = false ,
96
+ List <String >? taskArgs,
97
+ String ? resultsPath,
98
+ String ? gitBranch,
99
+ String ? luciBuilder,
100
+ @visibleForTesting Map <String , String >? isolateParams,
101
+ }) async {
102
+ section ('Running task "$taskName "' );
103
+ final TaskResult result = await runTask (
104
+ taskName,
105
+ deviceId: deviceId,
106
+ localEngine: localEngine,
107
+ localEngineSrcPath: localEngineSrcPath,
108
+ silent: silent,
109
+ taskArgs: taskArgs,
110
+ isolateParams: isolateParams,
111
+ );
112
+
113
+ print ('Task result:' );
114
+ print (const JsonEncoder .withIndent (' ' ).convert (result));
115
+ section ('Finished task "$taskName "' );
116
+
117
+ if (resultsPath != null ) {
118
+ final Cocoon cocoon = Cocoon ();
119
+ await cocoon.writeTaskResultToFile (
120
+ builderName: luciBuilder,
121
+ gitBranch: gitBranch,
122
+ result: result,
123
+ resultsPath: resultsPath,
124
+ );
125
+ }
126
+ return result;
127
+ }
128
+
64
129
/// Runs a task in a separate Dart VM and collects the result using the VM
65
130
/// service protocol.
66
131
///
0 commit comments