1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert';
import 'dart:io';
/// A result of running a single task.
class TaskResult {
TaskResult.buildOnly()
: succeeded = true,
data = null,
detailFiles = null,
benchmarkScoreKeys = null,
message = 'No tests run';
/// Constructs a successful result.
TaskResult.success(this.data, {
this.benchmarkScoreKeys = const <String>[],
this.detailFiles = const <String>[],
this.message = 'success',
})
: succeeded = true {
const JsonEncoder prettyJson = JsonEncoder.withIndent(' ');
if (benchmarkScoreKeys != null) {
for (final String key in benchmarkScoreKeys!) {
if (!data!.containsKey(key)) {
throw 'Invalid benchmark score key "$key". It does not exist in task '
'result data ${prettyJson.convert(data)}';
} else if (data![key] is! num) {
throw 'Invalid benchmark score for key "$key". It is expected to be a num '
'but was ${(data![key] as Object).runtimeType}: ${prettyJson.convert(data![key])}';
}
}
}
}
/// Constructs a successful result using JSON data stored in a file.
factory TaskResult.successFromFile(File file, {
List<String> benchmarkScoreKeys = const <String>[],
List<String> detailFiles = const <String>[],
}) {
return TaskResult.success(
json.decode(file.readAsStringSync()) as Map<String, dynamic>?,
benchmarkScoreKeys: benchmarkScoreKeys,
detailFiles: detailFiles,
);
}
/// Constructs a [TaskResult] from JSON.
factory TaskResult.fromJson(Map<String, dynamic> json) {
final bool success = json['success'] as bool;
if (success) {
final List<String> benchmarkScoreKeys = (json['benchmarkScoreKeys'] 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>?,
benchmarkScoreKeys: benchmarkScoreKeys,
detailFiles: detailFiles,
message: json['reason'] as String?,
);
}
return TaskResult.failure(json['reason'] as String?);
}
/// Constructs an unsuccessful result.
TaskResult.failure(this.message)
: succeeded = false,
data = null,
detailFiles = null,
benchmarkScoreKeys = null;
/// Whether the task succeeded.
final bool succeeded;
/// Task-specific JSON data
final Map<String, dynamic>? data;
/// Files containing detail on the run (e.g. timeline trace files)
final List<String>? detailFiles;
/// Keys in [data] that store scores that will be submitted to Cocoon.
///
/// Each key is also part of a benchmark's name tracked by Cocoon.
final List<String>? benchmarkScoreKeys;
/// Whether the task failed.
bool get failed => !succeeded;
/// Explains the result in a human-readable format.
final String? message;
/// Serializes this task result to JSON format.
///
/// The JSON format is as follows:
///
/// {
/// "success": true|false,
/// "data": arbitrary JSON data valid only for successful results,
/// "detailFiles": list of filenames containing detail on the run
/// "benchmarkScoreKeys": [
/// contains keys into "data" that represent benchmarks scores, which
/// can be uploaded, for example. to golem, valid only for successful
/// results
/// ],
/// "reason": failure reason string valid only for unsuccessful results
/// }
Map<String, dynamic> toJson() {
final Map<String, dynamic> json = <String, dynamic>{
'success': succeeded,
};
if (succeeded) {
json['data'] = data;
json['detailFiles'] = detailFiles;
json['benchmarkScoreKeys'] = benchmarkScoreKeys;
}
if (message != null || !succeeded) {
json['reason'] = message;
}
return json;
}
@override
String toString() => message ?? '';
}
class TaskResultCheckProcesses extends TaskResult {
TaskResultCheckProcesses() : super.success(null);
}