| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /// Scans past dart2js-windows test steps for timeouts and reports the | 5 /// Scans past dart2js-windows test steps for timeouts and reports the |
| 6 /// frequency of each test that has timed out. | 6 /// frequency of each test that has timed out. |
| 7 | 7 |
| 8 import 'dart:async'; | 8 import 'dart:async'; |
| 9 import 'dart:io'; | 9 import 'dart:io'; |
| 10 import 'package:args/args.dart'; | 10 import 'package:args/args.dart'; |
| 11 import 'package:gardening/src/buildbot_data.dart'; | 11 import 'package:gardening/src/buildbot_data.dart'; |
| 12 import 'package:gardening/src/buildbot_loading.dart'; | 12 import 'package:gardening/src/buildbot_loading.dart'; |
| 13 import 'package:gardening/src/buildbot_structures.dart'; | 13 import 'package:gardening/src/buildbot_structures.dart'; |
| 14 import 'package:gardening/src/client.dart'; |
| 14 import 'package:gardening/src/logdog.dart' as logdog; | 15 import 'package:gardening/src/logdog.dart' as logdog; |
| 15 import 'package:gardening/src/util.dart'; | 16 import 'package:gardening/src/util.dart'; |
| 16 | 17 |
| 17 main(List<String> args) async { | 18 main(List<String> args) async { |
| 18 ArgParser argParser = createArgParser(); | 19 ArgParser argParser = createArgParser(); |
| 19 argParser.addFlag('logdog', | |
| 20 negatable: false, help: "Pull test results from logdog."); | |
| 21 argParser.addOption('start', | 20 argParser.addOption('start', |
| 22 defaultsTo: '-2', | 21 defaultsTo: '-2', |
| 23 help: "Start pulling from the specified <build-number>.\n" | 22 help: "Start pulling from the specified <build-number>.\n" |
| 24 "Use negative numbers for the most recent builds;\n" | 23 "Use negative numbers for the most recent builds;\n" |
| 25 "for instance -2 for the second-to-last build.'"); | 24 "for instance -2 for the second-to-last build.'"); |
| 26 ArgResults argResults = argParser.parse(args); | 25 ArgResults argResults = argParser.parse(args); |
| 27 processArgResults(argResults); | 26 processArgResults(argResults); |
| 27 |
| 28 BuildbotClient client = argResults['logdog'] |
| 29 ? new LogdogBuildbotClient() |
| 30 : new HttpBuildbotClient(); |
| 31 |
| 28 List<String> arguments = argResults.rest; | 32 List<String> arguments = argResults.rest; |
| 29 if (arguments.length > 1) { | 33 if (arguments.length > 1) { |
| 30 print('Usage: find_timeouts.dart [options] [<count>]'); | 34 print('Usage: find_timeouts.dart [options] [<count>]'); |
| 31 print('Where <count> is the number of old builds that are scanned'); | 35 print('Where <count> is the number of old builds that are scanned'); |
| 32 print('and options are:'); | 36 print('and options are:'); |
| 33 print(argParser.usage); | 37 print(argParser.usage); |
| 34 exit(1); | 38 exit(1); |
| 35 } | 39 } |
| 36 int buildNumberCount = 10; | 40 int buildNumberCount = 10; |
| 37 if (arguments.length > 0) { | 41 if (arguments.length > 0) { |
| 38 buildNumberCount = int.parse(arguments[0]); | 42 buildNumberCount = int.parse(arguments[0]); |
| 39 } | 43 } |
| 40 int buildNumberOffset = int.parse(argResults['start']); | 44 int buildNumberOffset; |
| 45 if (argResults.wasParsed('start')) { |
| 46 buildNumberOffset = int.parse(argResults['start']); |
| 47 } else { |
| 48 buildNumberOffset = client.mostRecentBuildNumber; |
| 49 } |
| 41 | 50 |
| 42 bool useLogDog = argResults['logdog']; | |
| 43 | |
| 44 HttpClient client = new HttpClient(); | |
| 45 BuildGroup group = | 51 BuildGroup group = |
| 46 buildGroups.firstWhere((g) => g.groupName == 'dart2js-windows'); | 52 buildGroups.firstWhere((g) => g.groupName == 'dart2js-windows'); |
| 47 Map<String, List<Timeout>> timeouts = <String, List<Timeout>>{}; | 53 Map<String, List<Timeout>> timeouts = <String, List<Timeout>>{}; |
| 48 for (BuildSubgroup subgroup in group.subgroups) { | 54 for (BuildSubgroup subgroup in group.subgroups) { |
| 49 if (useLogDog) { | 55 await readBuildBotResults(client, subgroup, timeouts, |
| 50 await readLogDogResults(subgroup, timeouts, | 56 buildNumberOffset: buildNumberOffset, |
| 51 buildNumberOffset: buildNumberOffset, | 57 buildNumberCount: buildNumberCount); |
| 52 buildNumberCount: buildNumberCount); | |
| 53 } else { | |
| 54 await readBuildBotResults(client, subgroup, timeouts, | |
| 55 buildNumberOffset: buildNumberOffset, | |
| 56 buildNumberCount: buildNumberCount); | |
| 57 } | |
| 58 } | 58 } |
| 59 | 59 |
| 60 List<String> sorted = timeouts.keys.toList() | 60 List<String> sorted = timeouts.keys.toList() |
| 61 ..sort((a, b) { | 61 ..sort((a, b) { |
| 62 return -timeouts[a].length.compareTo(timeouts[b].length); | 62 return -timeouts[a].length.compareTo(timeouts[b].length); |
| 63 }); | 63 }); |
| 64 | 64 |
| 65 sorted.forEach((String testName) { | 65 sorted.forEach((String testName) { |
| 66 List<Timeout> list = timeouts[testName]; | 66 List<Timeout> list = timeouts[testName]; |
| 67 print('${padLeft('${list.length}', 4)} $testName'); | 67 print('${padLeft('${list.length}', 4)} $testName'); |
| 68 for (Timeout timeout in list) { | 68 for (Timeout timeout in list) { |
| 69 print(' - ${timeout.buildUri.botName}/${timeout.buildUri.stepName} ' | 69 print(' - ${timeout.buildUri.botName}/${timeout.buildUri.stepName} ' |
| 70 '${timeout.timeout.id} (${timeout.buildNumber})'); | 70 '${timeout.timeout.id} (${timeout.buildNumber})'); |
| 71 } | 71 } |
| 72 }); | 72 }); |
| 73 | 73 |
| 74 client.close(); | 74 client.close(); |
| 75 } | 75 } |
| 76 | 76 |
| 77 Future readLogDogResults( | 77 Future readLogDogResults( |
| 78 BuildSubgroup subgroup, Map<String, List<Timeout>> timeouts, | 78 BuildSubgroup subgroup, Map<String, List<Timeout>> timeouts, |
| 79 {int buildNumberOffset, int buildNumberCount}) async { | 79 {int buildNumberOffset, int buildNumberCount}) async { |
| 80 Map<String, String> subgroupPaths = subgroup.logDogPaths; | 80 Map<String, String> subgroupPaths = subgroup.logDogPaths; |
| 81 for (String shardName in subgroupPaths.keys) { | 81 for (String shardName in subgroupPaths.keys) { |
| 82 String subgroupPath = subgroupPaths[shardName]; | 82 String subgroupPath = subgroupPaths[shardName]; |
| 83 List<int> buildNumbers = <int>[]; | 83 List<int> buildNumbers = <int>[]; |
| 84 for (String line in logdog.ls(subgroupPath).split('\n')) { | 84 String text = await logdog.ls(subgroupPath); |
| 85 for (String line in text.split('\n')) { |
| 85 line = line.trim(); | 86 line = line.trim(); |
| 86 if (line.isNotEmpty) { | 87 if (line.isNotEmpty) { |
| 87 buildNumbers.add(int.parse(line)); | 88 buildNumbers.add(int.parse(line)); |
| 88 } | 89 } |
| 89 } | 90 } |
| 90 buildNumbers.sort((a, b) => -a.compareTo(b)); | 91 buildNumbers.sort((a, b) => -a.compareTo(b)); |
| 91 int buildNumberIndex; | 92 int buildNumberIndex; |
| 92 if (buildNumberOffset < 0) { | 93 if (buildNumberOffset < 0) { |
| 93 buildNumberIndex = -buildNumberOffset - 1; | 94 buildNumberIndex = -buildNumberOffset - 1; |
| 94 } else { | 95 } else { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 105 timeouts.putIfAbsent(timeout.id.testName, () => <Timeout>[]).add( | 106 timeouts.putIfAbsent(timeout.id.testName, () => <Timeout>[]).add( |
| 106 new Timeout(subgroup, result.buildNumber, buildUri, timeout)); | 107 new Timeout(subgroup, result.buildNumber, buildUri, timeout)); |
| 107 } | 108 } |
| 108 buildUri = buildUri.prev(); | 109 buildUri = buildUri.prev(); |
| 109 } | 110 } |
| 110 } | 111 } |
| 111 } | 112 } |
| 112 } | 113 } |
| 113 } | 114 } |
| 114 | 115 |
| 115 Future readBuildBotResults(HttpClient client, BuildSubgroup subgroup, | 116 Future readBuildBotResults(BuildbotClient client, BuildSubgroup subgroup, |
| 116 Map<String, List<Timeout>> timeouts, | 117 Map<String, List<Timeout>> timeouts, |
| 117 {int buildNumberOffset, int buildNumberCount}) async { | 118 {int buildNumberOffset, int buildNumberCount}) async { |
| 118 List<BuildUri> buildUris = subgroup.createUris(buildNumberOffset); | 119 List<BuildUri> buildUris = subgroup.createUris(buildNumberOffset); |
| 119 for (BuildUri buildUri in buildUris) { | 120 for (BuildUri buildUri in buildUris) { |
| 120 for (int i = 0; i < buildNumberCount; i++) { | 121 for (int i = 0; i < buildNumberCount; i++) { |
| 121 BuildResult result = await readBuildResult(client, buildUri); | 122 BuildResult result = await client.readResult(buildUri); |
| 122 for (TestFailure timeout in result.timeouts) { | 123 for (TestFailure timeout in result.timeouts) { |
| 123 timeouts | 124 timeouts |
| 124 .putIfAbsent(timeout.id.testName, () => <Timeout>[]) | 125 .putIfAbsent(timeout.id.testName, () => <Timeout>[]) |
| 125 .add(new Timeout(subgroup, result.buildNumber, buildUri, timeout)); | 126 .add(new Timeout(subgroup, result.buildNumber, buildUri, timeout)); |
| 126 } | 127 } |
| 127 buildUri = result.buildUri.prev(); | 128 buildUri = result.buildUri.prev(); |
| 128 } | 129 } |
| 129 } | 130 } |
| 130 } | 131 } |
| 131 | 132 |
| 132 class Timeout { | 133 class Timeout { |
| 133 final BuildSubgroup subgroup; | 134 final BuildSubgroup subgroup; |
| 134 final int buildNumber; | 135 final int buildNumber; |
| 135 final BuildUri buildUri; | 136 final BuildUri buildUri; |
| 136 final TestFailure timeout; | 137 final TestFailure timeout; |
| 137 | 138 |
| 138 Timeout(this.subgroup, this.buildNumber, this.buildUri, this.timeout); | 139 Timeout(this.subgroup, this.buildNumber, this.buildUri, this.timeout); |
| 139 } | 140 } |
| OLD | NEW |