Skip to content

Commit

Permalink
Merge a7312e5 into 1f00603
Browse files Browse the repository at this point in the history
  • Loading branch information
kevmoo committed Jul 2, 2015
2 parents 1f00603 + a7312e5 commit 9ebd76e
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 29 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
They can be used independently to limit the files which are included in the
output.

* Added `runAndCollect` API to library.

###0.7.1

* Added `collect` top-level method.
Expand Down
5 changes: 3 additions & 2 deletions lib/coverage.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
library coverage;

export 'src/hitmap.dart';
export 'src/collect.dart';
export 'src/formatter.dart';
export 'src/hitmap.dart';
export 'src/resolver.dart';
export 'src/collect.dart';
export 'src/run_and_collect.dart';
13 changes: 7 additions & 6 deletions lib/src/collect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,18 @@ Future<Map> _getAllCoverage(VMService service) async {

Future _resumeIsolates(VMService service) async {
var vm = await service.getVM();
var isolateRequests = vm.isolates.map((i) => service.resume(i.id));
return Future.wait(isolateRequests);
for (var isolate in vm.isolates) {
await service.resume(isolate.id);
}
}

Future _waitIsolatesPaused(VMService service, {Duration timeout}) async {
allPaused() async {
var vm = await service.getVM();
var isolateRequests = vm.isolates.map((i) => service.getIsolate(i.id));
var isolates = await Future.wait(isolateRequests);
var paused = isolates.every((i) => i.paused);
if (!paused) throw "Unpaused isolates remaining.";
for (var isolateRef in vm.isolates) {
var isolate = await service.getIsolate(isolateRef.id);
if (!isolate.paused) throw "Unpaused isolates remaining.";
}
}
return retry(allPaused, _retryInterval, timeout: timeout);
}
43 changes: 43 additions & 0 deletions lib/src/run_and_collect.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) 2015, 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.

library coverage.run_and_collect;

import 'dart:async';
import 'dart:io';

import 'collect.dart';
import 'util.dart';

Future<Map> runAndCollect(String scriptPath,
{List<String> scriptArgs, String packageRoot, Duration timeout}) async {
var openPort = await getOpenPort();

var dartArgs = ['--enable-vm-service=$openPort', '--pause_isolates_on_exit',];

if (packageRoot != null) {
dartArgs.add('--package-root=$packageRoot');
}

dartArgs.add(scriptPath);

if (scriptArgs != null) {
dartArgs.addAll(scriptArgs);
}

var process = await Process.start('dart', dartArgs);

try {
return collect('127.0.0.1', openPort, true, true, timeout: timeout);
} finally {
await process.stdout.drain();
await process.stderr.drain();

var code = await process.exitCode;

if (code < 0) {
throw "A critical exception happened in the process: exit code $code";
}
}
}
20 changes: 20 additions & 0 deletions lib/src/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
library coverage.src.util;

import 'dart:async';
import 'dart:io';

/// Retries the specified function with the specified interval and returns
/// the result on successful completion.
Expand Down Expand Up @@ -44,3 +45,22 @@ Future retry(Future f(), Duration interval, {Duration timeout}) async {
}
}, duration: timeout);
}

/// Returns an open port by creating a temporary Socket
Future<int> getOpenPort() async {
ServerSocket socket;

try {
socket = await ServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0);
} catch (_) {
// try again v/ V6 only. Slight possibility that V4 is disabled
socket = await ServerSocket.bind(InternetAddress.LOOPBACK_IP_V6, 0,
v6Only: true);
}

try {
return socket.port;
} finally {
await socket.close();
}
}
13 changes: 6 additions & 7 deletions test/collect_coverage_api_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import 'dart:async';
import 'dart:io';

import 'package:coverage/coverage.dart';
import 'package:coverage/src/util.dart';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';

final _sampleAppPath = p.join('test', 'test_files', 'test_app.dart');
import 'test_util.dart';

final _isolateLibPath = p.join('test', 'test_files', 'test_app_isolate.dart');

final _sampleAppFileUri = p.toUri(p.absolute(_sampleAppPath)).toString();
final _sampleAppFileUri = p.toUri(p.absolute(testAppPath)).toString();
final _isolateLibFileUri = p.toUri(p.absolute(_isolateLibPath)).toString();

const _timeout = const Duration(seconds: 5);
Expand Down Expand Up @@ -58,17 +60,14 @@ Future<Map> _getCoverageResult() async {
}

Future<Map> _collectCoverage() async {
// need to find an open port
var socket = await ServerSocket.bind(InternetAddress.ANY_IP_V4, 0);
int openPort = socket.port;
await socket.close();
var openPort = await getOpenPort();

// run the sample app, with the right flags
var sampleProcFuture = Process
.run('dart', [
'--enable-vm-service=$openPort',
'--pause_isolates_on_exit',
_sampleAppPath
testAppPath
])
.timeout(_timeout, onTimeout: () {
throw 'We timed out waiting for the sample app to finish.';
Expand Down
31 changes: 17 additions & 14 deletions test/collect_coverage_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import 'dart:convert';
import 'dart:io';

import 'package:coverage/coverage.dart';
import 'package:coverage/src/util.dart';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';

final _sampleAppPath = p.join('test', 'test_files', 'test_app.dart');
import 'test_util.dart';

final _isolateLibPath = p.join('test', 'test_files', 'test_app_isolate.dart');
final _collectAppPath = p.join('bin', 'collect_coverage.dart');

final _sampleAppFileUri = p.toUri(p.absolute(_sampleAppPath)).toString();
final _sampleAppFileUri = p.toUri(p.absolute(testAppPath)).toString();
final _isolateLibFileUri = p.toUri(p.absolute(_isolateLibPath)).toString();

const _timeout = const Duration(seconds: 5);
Expand Down Expand Up @@ -71,15 +73,19 @@ void main() {
test('parseCoverage', () async {
var tempDir = await Directory.systemTemp.createTemp('coverage.test.');

var outputFile = new File(p.join(tempDir.path, 'coverage.json'));
try {
var outputFile = new File(p.join(tempDir.path, 'coverage.json'));

var coverageResults = await _getCoverageResult();
await outputFile.writeAsString(coverageResults, flush: true);
var coverageResults = await _getCoverageResult();
await outputFile.writeAsString(coverageResults, flush: true);

var parsedResult = await parseCoverage([outputFile], 1);
var parsedResult = await parseCoverage([outputFile], 1);

expect(parsedResult, contains(_sampleAppFileUri));
expect(parsedResult, contains(_isolateLibFileUri));
expect(parsedResult, contains(_sampleAppFileUri));
expect(parsedResult, contains(_isolateLibFileUri));
} finally {
await tempDir.delete(recursive: true);
}
});
}

Expand All @@ -93,19 +99,16 @@ Future<String> _getCoverageResult() async {
}

Future<String> _collectCoverage() async {
expect(await FileSystemEntity.isFile(_sampleAppPath), isTrue);
expect(await FileSystemEntity.isFile(testAppPath), isTrue);

// need to find an open port
var socket = await ServerSocket.bind(InternetAddress.ANY_IP_V4, 0);
int openPort = socket.port;
await socket.close();
var openPort = await getOpenPort();

// run the sample app, with the right flags
var sampleProcFuture = Process
.run('dart', [
'--enable-vm-service=$openPort',
'--pause_isolates_on_exit',
_sampleAppPath
testAppPath
])
.timeout(_timeout, onTimeout: () {
throw 'We timed out waiting for the sample app to finish.';
Expand Down
55 changes: 55 additions & 0 deletions test/run_and_collect_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) 2015, 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.

library coverage.test.run_and_collect_test;

import 'package:coverage/coverage.dart';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';

import 'test_util.dart';

final _isolateLibPath = p.join('test', 'test_files', 'test_app_isolate.dart');

final _sampleAppFileUri = p.toUri(p.absolute(testAppPath)).toString();
final _isolateLibFileUri = p.toUri(p.absolute(_isolateLibPath)).toString();

void main() {
test('runAndCollect', () async {
// use runAndCollect and verify that the results match w/ running manually

var json = await runAndCollect(testAppPath);

expect(json.keys, unorderedEquals(['type', 'coverage']));

expect(json, containsPair('type', 'CodeCoverage'));

var coverage = json['coverage'] as List;
expect(coverage, isNotEmpty);

var sources = coverage.fold(<String, dynamic>{}, (Map map, Map value) {
var sourceUri = value['source'];

map.putIfAbsent(sourceUri, () => <Map>[]).add(value);

return map;
});

for (var sampleCoverageData in sources[_sampleAppFileUri]) {
expect(sampleCoverageData['hits'], isNotEmpty);
}

for (var sampleCoverageData in sources[_isolateLibFileUri]) {
expect(sampleCoverageData['hits'], isNotEmpty);
}

var hitMap = createHitmap(coverage);

expect(hitMap, contains(_sampleAppFileUri));

var isolateFile = hitMap[_isolateLibFileUri];

expect(isolateFile, {11: 1, 12: 1, 14: 1, 16: 3, 18: 1});
});
}
2 changes: 2 additions & 0 deletions test/test_all.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import 'package:test/test.dart';
import 'collect_coverage_test.dart' as collect_coverage;
import 'collect_coverage_test.dart' as collect_coverage_api;
import 'lcov_test.dart' as lcov;
import 'run_and_collect_test.dart' as run_and_collect;
import 'util_test.dart' as util;

void main() {
group('collect_coverage', collect_coverage.main);
group('collect_coverage_api', collect_coverage_api.main);
group('lcov', lcov.main);
group('run_and_collect', run_and_collect.main);
group('util', util.main);
}
9 changes: 9 additions & 0 deletions test/test_util.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) 2015, 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.

library coverage.test.util;

import 'package:path/path.dart' as p;

final testAppPath = p.join('test', 'test_files', 'test_app.dart');

0 comments on commit 9ebd76e

Please sign in to comment.