| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| // Add fields with data about the test run and the commit tested, and | |
| // with the result on the last build tested, to the test results file. | |
| import 'dart:convert'; | |
| import 'dart:io'; | |
| import 'package:test_runner/bot_results.dart'; | |
| const skipped = 'skipped'; | |
| void main(List<String> args) async { | |
| final resultsPath = args[0]; | |
| final priorResultsPath = args[1]; | |
| final flakyPath = args[2]; | |
| final priorFlakyPath = args[3]; | |
| final builderName = args[4]; | |
| final buildNumber = args[5]; | |
| final commitTime = int.parse(args[6]); | |
| final commitHash = args[7]; | |
| final newResultsPath = args[8]; | |
| // Load the input and the flakiness data if specified. | |
| final results = await loadResultsMap(resultsPath); | |
| final priorResults = await loadResultsMap(priorResultsPath); | |
| final flakes = await loadResultsMap(flakyPath); | |
| final priorFlakes = await loadResultsMap(priorFlakyPath); | |
| final firstPriorResult = | |
| priorResults.isEmpty ? null : priorResults.values.first; | |
| priorResults.forEach((key, priorResult) { | |
| if (priorResult['result'] != skipped) { | |
| results.putIfAbsent(key, () => constructNotRunResult(priorResult)); | |
| } | |
| }); | |
| for (final String key in results.keys) { | |
| final Map<String, dynamic> result = results[key]!; | |
| final Map<String, dynamic>? priorResult = priorResults[key]; | |
| final Map<String, dynamic>? flaky = flakes[key]; | |
| final Map<String, dynamic>? priorFlaky = priorFlakes[key]; | |
| result['commit_hash'] = commitHash; | |
| result['commit_time'] = commitTime; | |
| result['build_number'] = buildNumber; | |
| result['builder_name'] = builderName; | |
| result['flaky'] = flaky != null && (flaky['active'] ?? true) == true; | |
| result['previous_flaky'] = | |
| priorFlaky != null && (priorFlaky['active'] ?? true) == true; | |
| if (firstPriorResult != null) { | |
| result['previous_commit_hash'] = firstPriorResult['commit_hash']; | |
| result['previous_commit_time'] = firstPriorResult['commit_time']; | |
| result['previous_build_number'] = firstPriorResult['build_number']; | |
| } | |
| if (priorResult != null) { | |
| result['previous_result'] = priorResult['result']; | |
| result['changed'] = !(result['result'] == result['previous_result'] && | |
| result['flaky'] == result['previous_flaky'] && | |
| result['expected'] == priorResult['expected']); | |
| } else { | |
| result['changed'] = true; | |
| } | |
| } | |
| final sink = File(newResultsPath).openWrite(); | |
| final sorted = results.keys.toList()..sort(); | |
| for (final key in sorted) { | |
| sink.writeln(jsonEncode(results[key])); | |
| } | |
| sink.close(); | |
| } | |
| Map<String, dynamic> constructNotRunResult(Map<String, dynamic> previous) => { | |
| for (final key in [ | |
| 'name', | |
| 'configuration', | |
| 'suite', | |
| 'test_name', | |
| 'expected' | |
| ]) | |
| key: previous[key], | |
| 'time_ms': 0, | |
| 'result': skipped, | |
| 'matches': true, | |
| 'bot_name': '', | |
| }; |