| // 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); |
| } |