Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: tools/full-coverage.dart

Issue 137143018: Adapt tools/full-coverage.dart to changes in the isolate API and coverage output format. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 import "dart:async"; 5 import "dart:async";
6 import "dart:convert"; 6 import "dart:convert";
7 import "dart:io"; 7 import "dart:io";
8 import "dart:isolate"; 8 import "dart:isolate";
9 import "dart:mirrors";
10 9
11 import "package:args/args.dart"; 10 import "package:args/args.dart";
12 import "package:path/path.dart"; 11 import "package:path/path.dart";
13 12
14 /// [Environment] stores gathered arguments information. 13 /// [Environment] stores gathered arguments information.
15 class Environment { 14 class Environment {
16 String sdkRoot; 15 String sdkRoot;
17 String pkgRoot; 16 String pkgRoot;
18 var input; 17 var input;
19 var output; 18 var output;
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 Map createHitmap(String rawJson, Resolver resolver) { 181 Map createHitmap(String rawJson, Resolver resolver) {
183 Map<String, Map<int,int>> hitMap = {}; 182 Map<String, Map<int,int>> hitMap = {};
184 183
185 addToMap(source, line, count) { 184 addToMap(source, line, count) {
186 if (!hitMap[source].containsKey(line)) { 185 if (!hitMap[source].containsKey(line)) {
187 hitMap[source][line] = 0; 186 hitMap[source][line] = 0;
188 } 187 }
189 hitMap[source][line] += count; 188 hitMap[source][line] += count;
190 } 189 }
191 190
192 JSON.decode(rawJson).forEach((Map e) { 191 JSON.decode(rawJson)['coverage'].forEach((Map e) {
193 String source = resolver.resolve(e["source"]); 192 String source = resolver.resolve(e["source"]);
194 if (source == null) { 193 if (source == null) {
195 // Couldnt resolve import, so skip this entry. 194 // Couldnt resolve import, so skip this entry.
196 return; 195 return;
197 } 196 }
198 if (!hitMap.containsKey(source)) { 197 if (!hitMap.containsKey(source)) {
199 hitMap[source] = {}; 198 hitMap[source] = {};
200 } 199 }
201 var hits = e["hits"]; 200 var hits = e["hits"];
202 // hits is a flat array of the following format: 201 // hits is a flat array of the following format:
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 if (FileSystemEntity.isDirectorySync(absPath)) { 247 if (FileSystemEntity.isDirectorySync(absPath)) {
249 return new Directory(absPath).listSync(recursive: true) 248 return new Directory(absPath).listSync(recursive: true)
250 .where((entity) => entity is File && 249 .where((entity) => entity is File &&
251 filePattern.hasMatch(basename(entity.path))) 250 filePattern.hasMatch(basename(entity.path)))
252 .toList(); 251 .toList();
253 } 252 }
254 253
255 return [new File(absPath)]; 254 return [new File(absPath)];
256 } 255 }
257 256
258 worker() { 257 worker(WorkMessage msg) {
259 final start = new DateTime.now().millisecondsSinceEpoch; 258 final start = new DateTime.now().millisecondsSinceEpoch;
260 String me = currentMirrorSystem().isolate.debugName;
261 259
262 port.receive((Message message, reply) { 260 var env = msg.environment;
263 if (message.type == Message.SHUTDOWN) { 261 List files = msg.files;
264 port.close(); 262 Resolver resolver = new Resolver(env);
263 var workerHitmap = {};
264 files.forEach((File fileEntry) {
265 // Read file sync, as it only contains 1 object.
266 String contents = fileEntry.readAsStringSync();
267 if (contents.length > 0) {
268 mergeHitmaps(createHitmap(contents, resolver), workerHitmap);
265 } 269 }
270 });
266 271
267 if (message.type == Message.WORK) { 272 if (env["verbose"]) {
268 var env = message.payload[0]; 273 final end = new DateTime.now().millisecondsSinceEpoch;
269 List files = message.payload[1]; 274 print("${msg.workerName}: Finished processing files. "
270 Resolver resolver = new Resolver(env); 275 "Took ${end - start} ms.");
271 var workerHitmap = {}; 276 }
272 files.forEach((File fileEntry) {
273 // Read file sync, as it only contains 1 object.
274 String contents = fileEntry.readAsStringSync();
275 if (contents.length > 0) {
276 mergeHitmaps(createHitmap(contents, resolver), workerHitmap);
277 }
278 });
279 if (env["verbose"]) {
280 final end = new DateTime.now().millisecondsSinceEpoch;
281 print("worker[${me}]: Finished processing files. "
282 "Took ${end - start} ms.");
283 }
284 reply.send(new Message(Message.RESULT, [workerHitmap, resolver.failed]));
285 }
286 277
287 }); 278 msg.replyPort.send(new ResultMessage(workerHitmap, resolver.failed));
288 } 279 }
289 280
290 class Message { 281 class WorkMessage {
291 static const int SHUTDOWN = 1; 282 final String workerName;
292 static const int RESULT = 2; 283 final Environment environment;
293 static const int WORK = 3; 284 final List files;
285 final SendPort replyPort;
286 WorkMessage(this.workerName, this.environment, this.files, this.replyPort);
287 }
294 288
295 final int type; 289 class ResultMessage {
296 final payload; 290 final hitmap;
297 291 final failedResolves;
298 Message(this.type, this.payload); 292 ResultMessage(this.hitmap, this.failedResolves);
299 } 293 }
300 294
301 final env = new Environment(); 295 final env = new Environment();
302 296
297 List<List> split(List list, int nBuckets) {
Ivan Posva 2014/02/03 04:32:02 Please at least add a TODO to come up with a more
rmacnak 2014/02/03 18:31:56 Done.
298 // Leftover goes in the last bucket.
299 var buckets = new List(nBuckets);
300 var bucketSize = list.length ~/ nBuckets;
301 var taken = 0;
302 for (int i = 0; i < nBuckets; i++) {
303 bool lastBucket = i + 1 == nBuckets;
304 var start = i * bucketSize;
305 var end = lastBucket ? list.length : start + bucketSize ;
306 buckets[i] = list.sublist(start, end);
307 taken += buckets[i].length;
308 }
309 if (taken != list.length) throw "Error splitting";
310 return buckets;
311 }
312
313 Future<ResultMessage> spawnWorker(name, environment, files) {
314 ReceivePort port = new ReceivePort();
315 var completer = new Completer();
316 port.listen((WorkMessage msg) {
Ivan Posva 2014/02/03 04:32:02 I am not certain the type here is correct. Don't y
rmacnak 2014/02/03 18:31:56 Fixed, plus one other failure in checked mode.
317 completer.complete(msg);
318 port.close();
319 });
320 var msg = new WorkMessage(name, environment, files, port.sendPort);
321 Isolate.spawn(worker, msg);
322 return completer.future;
323 }
324
303 main(List<String> arguments) { 325 main(List<String> arguments) {
304 parseArgs(arguments); 326 parseArgs(arguments);
305 327
306 List files = filesToProcess(env.input); 328 List files = filesToProcess(env.input);
307 int filesPerWorker = files.length ~/ env.workers;
308 List workerPorts = [];
309 int doneCnt = 0;
310 329
311 List failedResolves = []; 330 List failedResolves = [];
312 List failedLoads = []; 331 List failedLoads = [];
313 Map globalHitmap = {}; 332 Map globalHitmap = {};
314 int start = new DateTime.now().millisecondsSinceEpoch; 333 int start = new DateTime.now().millisecondsSinceEpoch;
315 334
316 if (env.verbose) { 335 if (env.verbose) {
317 print("Environment:"); 336 print("Environment:");
318 print(" # files: ${files.length}"); 337 print(" # files: ${files.length}");
319 print(" # workers: ${env.workers}"); 338 print(" # workers: ${env.workers}");
320 print(" sdk-root: ${env.sdkRoot}"); 339 print(" sdk-root: ${env.sdkRoot}");
321 print(" package-root: ${env.pkgRoot}"); 340 print(" package-root: ${env.pkgRoot}");
322 } 341 }
323 342
324 port.receive((Message message, reply) {
325 if (message.type == Message.RESULT) {
326 mergeHitmaps(message.payload[0], globalHitmap);
327 failedResolves.addAll(message.payload[1]);
328 doneCnt++;
329 }
330
331 // All workers are done. Process the data.
332 if (doneCnt == env.workers) {
333 workerPorts.forEach((p) => p.send(new Message(Message.SHUTDOWN, null)));
334 if (env.verbose) {
335 final end = new DateTime.now().millisecondsSinceEpoch;
336 print("Done creating a global hitmap. Took ${end - start} ms.");
337 }
338
339 Future out;
340 if (env.prettyPrint) {
341 out = prettyPrint(globalHitmap, failedLoads);
342 }
343 if (env.lcov) {
344 out = lcov(globalHitmap);
345 }
346
347 out.then((_) {
348 env.output.close().then((_) {
349 if (env.verbose) {
350 final end = new DateTime.now().millisecondsSinceEpoch;
351 print("Done flushing output. Took ${end - start} ms.");
352 }
353 });
354 port.close();
355
356 if (env.verbose) {
357 if (failedResolves.length > 0) {
358 print("Failed to resolve:");
359 failedResolves.toSet().forEach((e) {
360 print(" ${e}");
361 });
362 }
363 if (failedLoads.length > 0) {
364 print("Failed to load:");
365 failedLoads.toSet().forEach((e) {
366 print(" ${e}");
367 });
368 }
369 }
370
371 });
372 }
373 });
374
375 Map sharedEnv = { 343 Map sharedEnv = {
376 "sdkRoot": env.sdkRoot, 344 "sdkRoot": env.sdkRoot,
377 "pkgRoot": env.pkgRoot, 345 "pkgRoot": env.pkgRoot,
378 "verbose": env.verbose, 346 "verbose": env.verbose,
379 }; 347 };
380 348
381 // Create workers. 349 // Create workers.
382 for (var i = 1; i < env.workers; i++) { 350 int workerId = 0;
383 var p = spawnFunction(worker); 351 var results = split(files, env.workers).map((workerFiles) {
384 workerPorts.add(p); 352 var result = spawnWorker("Worker ${workerId++}", sharedEnv, workerFiles);
385 var start = files.length - filesPerWorker; 353 return result.then((ResultMessage message) {
386 var end = files.length; 354 mergeHitmaps(message.hitmap, globalHitmap);
387 var workerFiles = files.getRange(start, end).toList(); 355 failedResolves.addAll(message.failedResolves);
388 files.removeRange(start, end); 356 });
389 p.send(new Message(Message.WORK, [sharedEnv, workerFiles]), port); 357 });
390 }
391 // Let the last worker deal with the rest of the files (which should be only
392 // off by at max (#workers - 1).
393 var p = spawnFunction(worker);
394 workerPorts.add(p);
395 p.send(new Message(Message.WORK, [sharedEnv, files]), port.toSendPort());
396 358
397 return 0; 359 Future.wait(results).then((ignore) {
360 // All workers are done. Process the data.
361 if (env.verbose) {
362 final end = new DateTime.now().millisecondsSinceEpoch;
363 print("Done creating a global hitmap. Took ${end - start} ms.");
364 }
365
366 Future out;
367 if (env.prettyPrint) {
368 out = prettyPrint(globalHitmap, failedLoads);
369 }
370 if (env.lcov) {
371 out = lcov(globalHitmap);
372 }
373
374 out.then((_) {
375 env.output.close().then((_) {
376 if (env.verbose) {
377 final end = new DateTime.now().millisecondsSinceEpoch;
378 print("Done flushing output. Took ${end - start} ms.");
379 }
380 });
381
382 if (env.verbose) {
383 if (failedResolves.length > 0) {
384 print("Failed to resolve:");
385 failedResolves.toSet().forEach((e) {
386 print(" ${e}");
387 });
388 }
389 if (failedLoads.length > 0) {
390 print("Failed to load:");
391 failedLoads.toSet().forEach((e) {
392 print(" ${e}");
393 });
394 }
395 }
396 });
397 });
398 } 398 }
399 399
400 /// Checks the validity of the provided arguments. Does not initialize actual 400 /// Checks the validity of the provided arguments. Does not initialize actual
401 /// processing. 401 /// processing.
402 parseArgs(List<String> arguments) { 402 parseArgs(List<String> arguments) {
403 var parser = new ArgParser(); 403 var parser = new ArgParser();
404 404
405 parser.addOption("sdk-root", abbr: "s", 405 parser.addOption("sdk-root", abbr: "s",
406 help: "path to the SDK root"); 406 help: "path to the SDK root");
407 parser.addOption("package-root", abbr: "p", 407 parser.addOption("package-root", abbr: "p",
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 } 493 }
494 494
495 try { 495 try {
496 env.workers = int.parse("${args["workers"]}"); 496 env.workers = int.parse("${args["workers"]}");
497 } catch (e) { 497 } catch (e) {
498 fail("Invalid worker count: $e"); 498 fail("Invalid worker count: $e");
499 } 499 }
500 500
501 env.verbose = args["verbose"]; 501 env.verbose = args["verbose"];
502 } 502 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698