blob: 778d6d82b20513fdfdfebef26285455ec81d97b4 [file] [log] [blame]
// Copyright (c) 2014, 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.
import 'dart:async';
import 'dart:convert' show JSON;
import 'dart:io';
import 'package:args/args.dart';
import 'package:coverage/src/devtools.dart';
import 'package:http/http.dart' as http;
Future<Map> getAllCoverage(Observatory observatory) {
return observatory.getIsolates()
.then((isolates) => isolates.map((i) => i.getCoverage()))
.then(Future.wait)
.then((responses) {
// flatten response lists
var allCoverage = responses.expand((it) => it).toList();
return {
'type': 'CodeCoverage',
'coverage': allCoverage,
};
});
}
Future unpinIsolates(Observatory observatory) {
return observatory.getIsolates()
.then((isolates) => isolates.map((i) => i.unpin()))
.then(Future.wait);
}
Future<Observatory> connect(String host, String port) {
return http.get('http://$host:$port/json').then((resp) {
var json = JSON.decode(resp.body);
if (json is List) {
return Observatory.connectOverDevtools(host, port);
}
return Observatory.connect(host, port);
});
}
void main(List<String> arguments) {
var options = parseArgs(arguments);
var watch = new Stopwatch()..start();
new Timer.periodic(new Duration(milliseconds: 200), (timer) {
connect(options.host, options.port).then((observatory) {
timer.cancel();
getAllCoverage(observatory)
.then(JSON.encode)
.then(options.out.write)
.then((_) => options.out.close())
.then((_) => options.unpin ? unpinIsolates(observatory) : null)
.then((_) => observatory.close());
}, onError: (_) {
if ((options.timeout != null) && (watch.elapsed > options.timeout)) {
var timeout = options.timeout.inSeconds;
print('Failed to collect coverage within ${timeout}s');
exit(1);
}
});
});
}
class Options {
final String host;
final String port;
final IOSink out;
final Duration timeout;
final bool unpin;
Options(this.host, this.port, this.out, this.timeout, this.unpin);
}
Options parseArgs(List<String> arguments) {
var parser = new ArgParser();
parser.addOption('host', abbr: 'H', defaultsTo: '127.0.0.1',
help: 'remote VM host');
parser.addOption('port', abbr: 'p', help: 'remote VM port');
parser.addOption('out', abbr: 'o', defaultsTo: 'stdout',
help: 'output: may be file or stdout');
parser.addOption('connect-timeout', abbr: 't',
help: 'connect timeout in seconds');
parser.addFlag('unpin-isolates', abbr: 'u', defaultsTo: false,
help: 'unpin all isolates on exit');
parser.addFlag('help', abbr: 'h', negatable: false,
help: 'show this help');
var args = parser.parse(arguments);
printUsage() {
print('Usage: dart collect_coverage.dart --port=NNNN [OPTION...]\n');
print(parser.getUsage());
}
fail(message) {
print('Error: $message\n');
printUsage();
exit(1);
}
if (args['help']) {
printUsage();
exit(0);
}
if (args['port'] == null) fail('port not specified');
var out;
if (args['out'] == 'stdout') {
out = stdout;
} else {
var outfile = new File(args['out'])
..createSync(recursive: true);
out = outfile.openWrite();
}
var timeout = (args['connect-timeout'] == null) ? null
: new Duration(seconds: int.parse(args['connect-timeout']));
return new Options(args['host'], args['port'], out, timeout,
args['unpin-isolates']);
}