blob: 6a4e5564affbfd87e3257d132bd4d99d75561a34 [file] [log] [blame]
// 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.
// ignore_for_file: only_throw_errors
import 'dart:async';
import 'package:coverage/src/util.dart';
import 'package:test/test.dart';
const _failCount = 5;
const _delay = Duration(milliseconds: 10);
void main() {
test('retry', () async {
var count = 0;
final stopwatch = Stopwatch()..start();
Future failCountTimes() async {
expect(stopwatch.elapsed, greaterThanOrEqualTo(_delay * count));
while (count < _failCount) {
count++;
throw 'not yet!';
}
return 42;
}
final value = await retry(failCountTimes, _delay) as int;
expect(value, 42);
expect(count, _failCount);
expect(stopwatch.elapsed, greaterThanOrEqualTo(_delay * count));
});
group('retry with timeout', () {
test('if it finishes', () async {
var count = 0;
final stopwatch = Stopwatch()..start();
Future failCountTimes() async {
expect(stopwatch.elapsed, greaterThanOrEqualTo(_delay * count));
while (count < _failCount) {
count++;
throw 'not yet!';
}
return 42;
}
final safeTimoutDuration = _delay * _failCount * 10;
final value = await retry(
failCountTimes,
_delay,
timeout: safeTimoutDuration,
) as int;
expect(value, 42);
expect(count, _failCount);
expect(stopwatch.elapsed, greaterThanOrEqualTo(_delay * count));
});
test('if it does not finish', () async {
var count = 0;
final stopwatch = Stopwatch()..start();
var caught = false;
var countAfterError = 0;
Future failCountTimes() async {
if (caught) {
countAfterError++;
}
expect(stopwatch.elapsed, greaterThanOrEqualTo(_delay * count));
count++;
throw 'never';
}
final unsafeTimeoutDuration = _delay * (_failCount / 2);
try {
await retry(failCountTimes, _delay, timeout: unsafeTimeoutDuration);
// ignore: avoid_catching_errors
} on StateError catch (e) {
expect(e.message, 'Failed to complete within 25ms');
caught = true;
expect(countAfterError, 0,
reason: 'Execution should stop after a timeout');
await Future<dynamic>.delayed(_delay * 3);
expect(countAfterError, 0, reason: 'Even after a delay');
}
expect(caught, isTrue);
});
});
group('extractVMServiceUri', () {
test('returns null when not found', () {
expect(extractVMServiceUri('foo bar baz'), isNull);
});
test('returns null for an incorrectly formatted URI', () {
const msg = 'Observatory listening on :://';
expect(extractVMServiceUri(msg), null);
});
test('returns URI at end of string', () {
const msg = 'Observatory listening on http://foo.bar:9999/';
expect(extractVMServiceUri(msg), Uri.parse('http://foo.bar:9999/'));
});
test('returns URI with auth token at end of string', () {
const msg = 'Observatory listening on http://foo.bar:9999/cG90YXRv/';
expect(
extractVMServiceUri(msg), Uri.parse('http://foo.bar:9999/cG90YXRv/'));
});
test('return URI embedded within string', () {
const msg = '1985-10-26 Observatory listening on http://foo.bar:9999/ **';
expect(extractVMServiceUri(msg), Uri.parse('http://foo.bar:9999/'));
});
test('return URI with auth token embedded within string', () {
const msg =
'1985-10-26 Observatory listening on http://foo.bar:9999/cG90YXRv/ **';
expect(
extractVMServiceUri(msg), Uri.parse('http://foo.bar:9999/cG90YXRv/'));
});
test('handles new Dart VM service message format', () {
const msg =
'The Dart VM service is listening on http://foo.bar:9999/cG90YXRv/';
expect(
extractVMServiceUri(msg), Uri.parse('http://foo.bar:9999/cG90YXRv/'));
});
});
group('getIgnoredLines', () {
const invalidSources = [
'''final str = ''; // coverage:ignore-start
final str = '';
final str = ''; // coverage:ignore-start
''',
'''final str = ''; // coverage:ignore-start
final str = '';
final str = ''; // coverage:ignore-start
final str = ''; // coverage:ignore-end
final str = '';
final str = ''; // coverage:ignore-end
''',
'''final str = ''; // coverage:ignore-start
final str = '';
final str = ''; // coverage:ignore-end
final str = '';
final str = ''; // coverage:ignore-end
''',
'''final str = ''; // coverage:ignore-end
final str = '';
final str = ''; // coverage:ignore-start
final str = '';
final str = ''; // coverage:ignore-end
''',
'''final str = ''; // coverage:ignore-end
final str = '';
final str = ''; // coverage:ignore-end
''',
'''final str = ''; // coverage:ignore-end
final str = '';
final str = ''; // coverage:ignore-start
''',
'''final str = ''; // coverage:ignore-end
''',
'''final str = ''; // coverage:ignore-start
''',
];
test('throws FormatException when the annotations are not balanced', () {
void runTest(int index, String errMsg) {
final content = invalidSources[index].split('\n');
expect(
() => getIgnoredLines('content-$index.dart', content),
throwsA(
allOf(
isFormatException,
predicate((FormatException e) => e.message == errMsg),
),
),
reason: 'expected FormatException with message "$errMsg"',
);
}
runTest(
0,
'coverage:ignore-start found at content-0.dart:'
'3 before previous coverage:ignore-start ended',
);
runTest(
1,
'coverage:ignore-start found at content-1.dart:'
'3 before previous coverage:ignore-start ended',
);
runTest(
2,
'unmatched coverage:ignore-end found at content-2.dart:5',
);
runTest(
3,
'unmatched coverage:ignore-end found at content-3.dart:1',
);
runTest(
4,
'unmatched coverage:ignore-end found at content-4.dart:1',
);
runTest(
5,
'unmatched coverage:ignore-end found at content-5.dart:1',
);
runTest(
6,
'unmatched coverage:ignore-end found at content-6.dart:1',
);
runTest(
7,
'coverage:ignore-start found at content-7.dart:'
'1 has no matching coverage:ignore-end',
);
});
test(
'returns [[0,lines.length]] when the annotations are not '
'balanced but the whole file is ignored', () {
for (final content in invalidSources) {
final lines = content.split('\n');
lines.add(' // coverage:ignore-file');
expect(getIgnoredLines('', lines), [
[0, lines.length]
]);
}
});
test('returns [[0,lines.length]] when the whole file is ignored', () {
final lines = '''final str = ''; // coverage:ignore-start
final str = ''; // coverage:ignore-end
final str = ''; // coverage:ignore-file
'''
.split('\n');
expect(getIgnoredLines('', lines), [
[0, lines.length]
]);
});
test('return the correct range of lines ignored', () {
final lines = '''
final str = ''; // coverage:ignore-start
final str = ''; // coverage:ignore-line
final str = ''; // coverage:ignore-end
final str = ''; // coverage:ignore-start
final str = ''; // coverage:ignore-line
final str = ''; // coverage:ignore-end
'''
.split('\n');
expect(getIgnoredLines('', lines), [
[1, 3],
[4, 6],
]);
});
test('return the correct list of lines ignored', () {
final lines = '''
final str = ''; // coverage:ignore-line
final str = ''; // coverage:ignore-line
final str = ''; // coverage:ignore-line
'''
.split('\n');
expect(getIgnoredLines('', lines), [
[1, 1],
[2, 2],
[3, 3],
]);
});
test('ignore comments have no effect inside string literals', () {
final lines = '''
final str = '// coverage:ignore-file';
final str = '// coverage:ignore-line';
final str = ''; // coverage:ignore-line
final str = '// coverage:ignore-start';
final str = '// coverage:ignore-end';
'''
.split('\n');
expect(getIgnoredLines('', lines), [
[3, 3],
]);
});
test('allow white-space after ignore comments', () {
// Using multiple strings, rather than splitting a multi-line string,
// because many code editors remove trailing white-space.
final lines = [
"final str = ''; // coverage:ignore-start ",
"final str = ''; // coverage:ignore-line\t",
"final str = ''; // coverage:ignore-end \t \t ",
"final str = ''; // coverage:ignore-line \t ",
"final str = ''; // coverage:ignore-start \t ",
"final str = ''; // coverage:ignore-end \t \t ",
];
expect(getIgnoredLines('', lines), [
[1, 3],
[4, 4],
[5, 6],
]);
});
test('allow omitting space after //', () {
final lines = [
"final str = ''; //coverage:ignore-start",
"final str = ''; //coverage:ignore-line",
"final str = ''; //coverage:ignore-end",
"final str = ''; //coverage:ignore-line",
"final str = ''; //coverage:ignore-start",
"final str = ''; //coverage:ignore-end",
];
expect(getIgnoredLines('', lines), [
[1, 3],
[4, 4],
[5, 6],
]);
});
test('allow text after ignore comments', () {
final lines = [
"final str = ''; // coverage:ignore-start due to XYZ",
"final str = ''; // coverage:ignore-line",
"final str = ''; // coverage:ignore-end due to XYZ",
"final str = ''; // coverage:ignore-line due to 123",
"final str = ''; // coverage:ignore-start",
"final str = ''; // coverage:ignore-end it is done",
];
expect(getIgnoredLines('', lines), [
[1, 3],
[4, 4],
[5, 6],
]);
});
});
}