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 |