| // 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'; |
| |
| class TestSpecs { |
| |
| TestSpecs({ |
| required this.path, |
| required this.startTime, |
| }); |
| |
| final String path; |
| int startTime; |
| int? _endTime; |
| |
| int get milliseconds { |
| return endTime - startTime; |
| } |
| |
| set endTime(int value) { |
| _endTime = value; |
| } |
| |
| int get endTime { |
| if (_endTime == null) { |
| return 0; |
| } |
| return _endTime!; |
| } |
| |
| String toJson() { |
| return json.encode( |
| <String, String>{'path': path, 'runtime': milliseconds.toString()} |
| ); |
| } |
| } |
| |
| class TestFileReporterResults { |
| TestFileReporterResults._({ |
| required this.allTestSpecs, |
| required this.hasFailedTests, |
| required this.errors, |
| }); |
| |
| /// Intended to parse the output file of `dart test --file-reporter json:file_name |
| factory TestFileReporterResults.fromFile(File metrics) { |
| if (!metrics.existsSync()) { |
| throw Exception('${metrics.path} does not exist'); |
| } |
| |
| final Map<int, TestSpecs> testSpecs = <int, TestSpecs>{}; |
| bool hasFailedTests = true; |
| final List<String> errors = <String>[]; |
| |
| for (final String metric in metrics.readAsLinesSync()) { |
| final Map<String, Object?> entry = json.decode(metric) as Map<String, Object?>; |
| if (entry.containsKey('suite')) { |
| final Map<String, Object?> suite = entry['suite']! as Map<String, Object?>; |
| addTestSpec(suite, entry['time']! as int, testSpecs); |
| } else if (isMetricDone(entry, testSpecs)) { |
| final Map<String, Object?> group = entry['group']! as Map<String, Object?>; |
| final int suiteID = group['suiteID']! as int; |
| addMetricDone(suiteID, entry['time']! as int, testSpecs); |
| } else if (entry.containsKey('error')) { |
| final String stackTrace = entry.containsKey('stackTrace') ? entry['stackTrace']! as String : ''; |
| errors.add('${entry['error']}\n $stackTrace'); |
| } else if (entry.containsKey('success') && entry['success'] == true) { |
| hasFailedTests = false; |
| } |
| } |
| |
| return TestFileReporterResults._(allTestSpecs: testSpecs, hasFailedTests: hasFailedTests, errors: errors); |
| } |
| |
| final Map<int, TestSpecs> allTestSpecs; |
| final bool hasFailedTests; |
| final List<String> errors; |
| |
| |
| static void addTestSpec(Map<String, Object?> suite, int time, Map<int, TestSpecs> allTestSpecs) { |
| allTestSpecs[suite['id']! as int] = TestSpecs( |
| path: suite['path']! as String, |
| startTime: time, |
| ); |
| } |
| |
| static void addMetricDone(int suiteID, int time, Map<int, TestSpecs> allTestSpecs) { |
| final TestSpecs testSpec = allTestSpecs[suiteID]!; |
| testSpec.endTime = time; |
| } |
| |
| static bool isMetricDone(Map<String, Object?> entry, Map<int, TestSpecs> allTestSpecs) { |
| if (entry.containsKey('group') && entry['type']! as String == 'group') { |
| final Map<String, Object?> group = entry['group']! as Map<String, Object?>; |
| return allTestSpecs.containsKey(group['suiteID']! as int); |
| } |
| return false; |
| } |
| } |