OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 import 'dart:async'; |
| 6 import 'dart:io'; |
| 7 import 'util.dart'; |
| 8 |
| 9 import 'buildbot_structures.dart'; |
| 10 import 'cache.dart'; |
| 11 import 'logdog.dart'; |
| 12 |
| 13 const String BUILDBOT_BUILDNUMBER = ' BUILDBOT_BUILDNUMBER: '; |
| 14 |
| 15 /// Read the build result for [buildUri]. |
| 16 /// |
| 17 /// The data is loaded from the cache, if available, otherwise [read] is called |
| 18 /// to fetch the data and stored in the cache afterwards. |
| 19 Future<BuildResult> _readBuildResult( |
| 20 BuildUri buildUri, Future<String> read()) async { |
| 21 if (buildUri.buildNumber < 0) { |
| 22 String text = await read(); |
| 23 BuildResult result = parseTestStepResult(buildUri, text); |
| 24 if (result.buildNumber != null) { |
| 25 cache.write(result.buildUri.logdogPath, text); |
| 26 } |
| 27 return result; |
| 28 } else { |
| 29 return parseTestStepResult( |
| 30 buildUri, await cache.read(buildUri.logdogPath, read)); |
| 31 } |
| 32 } |
| 33 |
| 34 /// Fetches test data for [buildUri] through the buildbot stdio. |
| 35 Future<BuildResult> readBuildResult( |
| 36 HttpClient client, BuildUri buildUri) async { |
| 37 Future<String> read() async { |
| 38 Uri uri = buildUri.toUri(); |
| 39 log('Reading buildbot results: $uri'); |
| 40 return await readUriAsText(client, uri); |
| 41 } |
| 42 |
| 43 return _readBuildResult(buildUri, read); |
| 44 } |
| 45 |
| 46 /// Fetches test data for [buildUri] through logdog. |
| 47 /// |
| 48 /// The build number of [buildUri] most be non-negative. |
| 49 Future<BuildResult> readLogDogResult(BuildUri buildUri) { |
| 50 Future<String> read() async { |
| 51 log('Reading logdog results: $buildUri'); |
| 52 return cat(buildUri.logdogPath); |
| 53 } |
| 54 |
| 55 return _readBuildResult(buildUri, read); |
| 56 } |
| 57 |
| 58 /// Parses a test status line of the from |
| 59 /// `Done <config-name> <arch-name> <test-name>: <status>`. |
| 60 /// |
| 61 /// If [line] is not of the correct form, `null` is returned. |
| 62 TestStatus parseTestStatus(String line) { |
| 63 try { |
| 64 List<String> parts = split(line, ['Done ', ' ', ' ', ': ']); |
| 65 String testName = parts[3]; |
| 66 String configName = parts[1]; |
| 67 String archName = parts[2]; |
| 68 String status = parts[4]; |
| 69 return new TestStatus( |
| 70 new TestConfiguration(configName, archName, testName), status); |
| 71 } catch (_) { |
| 72 return null; |
| 73 } |
| 74 } |
| 75 |
| 76 /// Parses the [buildUri] test log and creates a [BuildResult] for it. |
| 77 BuildResult parseTestStepResult(BuildUri buildUri, String text) { |
| 78 log('Parsing results: $buildUri (${text.length} bytes)'); |
| 79 int buildNumber; |
| 80 List<String> currentFailure; |
| 81 bool parsingTimingBlock = false; |
| 82 |
| 83 List<TestStatus> results = <TestStatus>[]; |
| 84 List<TestFailure> failures = <TestFailure>[]; |
| 85 List<Timing> timings = <Timing>[]; |
| 86 for (String line in text.split('\n')) { |
| 87 if (line.startsWith(BUILDBOT_BUILDNUMBER)) { |
| 88 buildNumber = |
| 89 int.parse(line.substring(BUILDBOT_BUILDNUMBER.length).trim()); |
| 90 } |
| 91 if (currentFailure != null) { |
| 92 if (line.startsWith('Done ')) { |
| 93 TestStatus status = parseTestStatus(line); |
| 94 if (status != null) { |
| 95 results.add(status); |
| 96 failures.add(new TestFailure(buildUri, currentFailure)); |
| 97 currentFailure = null; |
| 98 } |
| 99 } else { |
| 100 currentFailure.add(line); |
| 101 } |
| 102 } else if (line.startsWith('FAILED:')) { |
| 103 currentFailure = <String>[]; |
| 104 currentFailure.add(line); |
| 105 } |
| 106 if (line.startsWith('--- Total time:')) { |
| 107 parsingTimingBlock = true; |
| 108 } else if (parsingTimingBlock) { |
| 109 if (line.startsWith('0:')) { |
| 110 timings.addAll(parseTimings(buildUri, line)); |
| 111 } else { |
| 112 parsingTimingBlock = false; |
| 113 } |
| 114 } |
| 115 } |
| 116 return new BuildResult(buildUri, buildNumber, results, failures, timings); |
| 117 } |
| 118 |
| 119 /// Create the [Timing]s for the [line] as found in the top-20 timings of a |
| 120 /// build step stdio log. |
| 121 List<Timing> parseTimings(BuildUri uri, String line) { |
| 122 List<String> parts = split(line, [' - ', ' - ', ' ']); |
| 123 String time = parts[0]; |
| 124 String stepName = parts[1]; |
| 125 String configName = parts[2]; |
| 126 String testNames = parts[3]; |
| 127 List<Timing> timings = <Timing>[]; |
| 128 for (String name in testNames.split(',')) { |
| 129 name = name.trim(); |
| 130 int slashPos = name.indexOf('/'); |
| 131 String archName = name.substring(0, slashPos); |
| 132 String testName = name.substring(slashPos + 1); |
| 133 timings.add(new Timing( |
| 134 uri, |
| 135 time, |
| 136 new TestStep( |
| 137 stepName, new TestConfiguration(configName, archName, testName)))); |
| 138 } |
| 139 return timings; |
| 140 } |
OLD | NEW |