2016-05-16 19:53:13 +00:00
|
|
|
// Copyright 2015 The Chromium Authors. 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';
|
2017-02-06 06:58:49 +00:00
|
|
|
import 'dart:io' as io;
|
2016-05-16 19:53:13 +00:00
|
|
|
|
2017-01-07 00:51:44 +00:00
|
|
|
import 'package:flutter_tools/src/base/file_system.dart';
|
2017-01-09 16:37:00 +00:00
|
|
|
import 'package:flutter_tools/src/base/io.dart';
|
2016-05-16 19:53:13 +00:00
|
|
|
import 'package:flutter_tools/src/cache.dart';
|
|
|
|
import 'package:flutter_tools/src/dart/sdk.dart';
|
|
|
|
import 'package:test/test.dart';
|
|
|
|
|
2017-05-12 17:44:52 +00:00
|
|
|
import '../src/context.dart';
|
2016-05-16 19:53:13 +00:00
|
|
|
|
|
|
|
// This test depends on some files in ///dev/automated_tests/flutter_test/*
|
|
|
|
|
2017-03-10 17:39:01 +00:00
|
|
|
Future<Null> _testExclusionLock;
|
|
|
|
|
2016-05-16 19:53:13 +00:00
|
|
|
void main() {
|
2017-06-30 00:26:19 +00:00
|
|
|
group('flutter test should', () {
|
2017-03-10 17:39:01 +00:00
|
|
|
|
2017-02-14 01:45:50 +00:00
|
|
|
final String automatedTestsDirectory = fs.path.join('..', '..', 'dev', 'automated_tests');
|
|
|
|
final String flutterTestDirectory = fs.path.join(automatedTestsDirectory, 'flutter_test');
|
2017-01-10 19:31:24 +00:00
|
|
|
|
2017-06-30 00:26:19 +00:00
|
|
|
testUsingContext('report nice errors for exceptions thrown within testWidgets()', () async {
|
2017-04-13 19:31:04 +00:00
|
|
|
Cache.flutterRoot = '../..';
|
|
|
|
return _testFile('exception_handling', automatedTestsDirectory, flutterTestDirectory);
|
2018-01-18 00:08:07 +00:00
|
|
|
}, skip: io.Platform.isWindows); // Dart on Windows has trouble with unicode characters in output
|
2017-04-13 19:31:04 +00:00
|
|
|
|
2017-06-30 00:26:19 +00:00
|
|
|
testUsingContext('report a nice error when a guarded function was called without await', () async {
|
2016-05-16 19:53:13 +00:00
|
|
|
Cache.flutterRoot = '../..';
|
2017-03-13 18:17:09 +00:00
|
|
|
return _testFile('test_async_utils_guarded', automatedTestsDirectory, flutterTestDirectory);
|
2018-01-18 00:08:07 +00:00
|
|
|
}, skip: io.Platform.isWindows); // Dart on Windows has trouble with unicode characters in output
|
2017-03-10 17:39:01 +00:00
|
|
|
|
2017-06-30 00:26:19 +00:00
|
|
|
testUsingContext('report a nice error when an async function was called without await', () async {
|
2016-05-16 19:53:13 +00:00
|
|
|
Cache.flutterRoot = '../..';
|
2017-03-13 18:17:09 +00:00
|
|
|
return _testFile('test_async_utils_unguarded', automatedTestsDirectory, flutterTestDirectory);
|
2018-01-18 00:08:07 +00:00
|
|
|
}, skip: io.Platform.isWindows); // Dart on Windows has trouble with unicode characters in output
|
2017-03-10 17:39:01 +00:00
|
|
|
|
2017-12-09 00:51:59 +00:00
|
|
|
testUsingContext('report a nice error when a Ticker is left running', () async {
|
|
|
|
Cache.flutterRoot = '../..';
|
|
|
|
return _testFile('ticker', automatedTestsDirectory, flutterTestDirectory);
|
2018-01-18 00:08:07 +00:00
|
|
|
}, skip: io.Platform.isWindows); // Dart on Windows has trouble with unicode characters in output
|
2017-12-09 00:51:59 +00:00
|
|
|
|
2017-06-30 00:26:19 +00:00
|
|
|
testUsingContext('report a nice error when a pubspec.yaml is missing a flutter_test dependency', () async {
|
2017-02-14 01:45:50 +00:00
|
|
|
final String missingDependencyTests = fs.path.join('..', '..', 'dev', 'missing_dependency_tests');
|
2017-01-10 19:31:24 +00:00
|
|
|
Cache.flutterRoot = '../..';
|
2017-03-13 18:17:09 +00:00
|
|
|
return _testFile('trivial', missingDependencyTests, missingDependencyTests);
|
2018-01-18 00:08:07 +00:00
|
|
|
}, skip: io.Platform.isWindows); // Dart on Windows has trouble with unicode characters in output
|
2017-06-30 00:26:19 +00:00
|
|
|
|
|
|
|
testUsingContext('run a test when its name matches a regexp', () async {
|
|
|
|
Cache.flutterRoot = '../..';
|
|
|
|
final ProcessResult result = await _runFlutterTest('filtering', automatedTestsDirectory, flutterTestDirectory,
|
2017-08-04 23:33:38 +00:00
|
|
|
extraArgs: const <String>['--name', 'inc.*de']);
|
|
|
|
if (!result.stdout.contains('+1: All tests passed'))
|
|
|
|
fail('unexpected output from test:\n\n${result.stdout}\n-- end stdout --\n\n');
|
2017-06-30 00:26:19 +00:00
|
|
|
expect(result.exitCode, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
testUsingContext('run a test when its name contains a string', () async {
|
|
|
|
Cache.flutterRoot = '../..';
|
|
|
|
final ProcessResult result = await _runFlutterTest('filtering', automatedTestsDirectory, flutterTestDirectory,
|
2017-08-04 23:33:38 +00:00
|
|
|
extraArgs: const <String>['--plain-name', 'include']);
|
|
|
|
if (!result.stdout.contains('+1: All tests passed'))
|
|
|
|
fail('unexpected output from test:\n\n${result.stdout}\n-- end stdout --\n\n');
|
|
|
|
expect(result.exitCode, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
testUsingContext('test runs to completion', () async {
|
|
|
|
Cache.flutterRoot = '../..';
|
|
|
|
final ProcessResult result = await _runFlutterTest('trivial', automatedTestsDirectory, flutterTestDirectory,
|
|
|
|
extraArgs: const <String>['--verbose']);
|
|
|
|
if ((!result.stdout.contains('+1: All tests passed')) ||
|
|
|
|
(!result.stdout.contains('test 0: starting shell process')) ||
|
|
|
|
(!result.stdout.contains('test 0: deleting temporary directory')) ||
|
|
|
|
(!result.stdout.contains('test 0: finished')) ||
|
|
|
|
(!result.stdout.contains('test package returned with exit code 0')))
|
|
|
|
fail('unexpected output from test:\n\n${result.stdout}\n-- end stdout --\n\n');
|
|
|
|
if (result.stderr.isNotEmpty)
|
|
|
|
fail('unexpected error output from test:\n\n${result.stderr}\n-- end stderr --\n\n');
|
2017-06-30 00:26:19 +00:00
|
|
|
expect(result.exitCode, 0);
|
|
|
|
});
|
|
|
|
|
2018-01-18 00:08:07 +00:00
|
|
|
});
|
2016-05-16 19:53:13 +00:00
|
|
|
}
|
|
|
|
|
2017-03-13 18:17:09 +00:00
|
|
|
Future<Null> _testFile(String testName, String workingDirectory, String testDirectory) async {
|
2017-02-14 01:45:50 +00:00
|
|
|
final String fullTestExpectation = fs.path.join(testDirectory, '${testName}_expectation.txt');
|
2017-01-07 00:51:44 +00:00
|
|
|
final File expectationFile = fs.file(fullTestExpectation);
|
2017-06-30 00:26:19 +00:00
|
|
|
if (!expectationFile.existsSync())
|
2017-08-04 23:33:38 +00:00
|
|
|
fail('missing expectation file: $expectationFile');
|
2017-03-10 17:39:01 +00:00
|
|
|
|
|
|
|
while (_testExclusionLock != null)
|
|
|
|
await _testExclusionLock;
|
|
|
|
|
2017-06-30 00:26:19 +00:00
|
|
|
final ProcessResult exec = await _runFlutterTest(testName, workingDirectory, testDirectory);
|
2017-03-10 17:39:01 +00:00
|
|
|
|
2017-03-13 18:17:09 +00:00
|
|
|
expect(exec.exitCode, isNonZero);
|
2016-05-16 19:53:13 +00:00
|
|
|
final List<String> output = exec.stdout.split('\n');
|
2017-03-22 18:07:58 +00:00
|
|
|
if (output.first == 'Waiting for another flutter command to release the startup lock...')
|
|
|
|
output.removeAt(0);
|
2017-01-10 19:31:24 +00:00
|
|
|
output.add('<<stderr>>');
|
|
|
|
output.addAll(exec.stderr.split('\n'));
|
2017-01-07 00:51:44 +00:00
|
|
|
final List<String> expectations = fs.file(fullTestExpectation).readAsLinesSync();
|
2016-05-16 19:53:13 +00:00
|
|
|
bool allowSkip = false;
|
|
|
|
int expectationLineNumber = 0;
|
|
|
|
int outputLineNumber = 0;
|
2017-01-10 19:31:24 +00:00
|
|
|
bool haveSeenStdErrMarker = false;
|
2016-05-16 19:53:13 +00:00
|
|
|
while (expectationLineNumber < expectations.length) {
|
|
|
|
expect(output, hasLength(greaterThan(outputLineNumber)));
|
|
|
|
final String expectationLine = expectations[expectationLineNumber];
|
|
|
|
final String outputLine = output[outputLineNumber];
|
|
|
|
if (expectationLine == '<<skip until matching line>>') {
|
|
|
|
allowSkip = true;
|
|
|
|
expectationLineNumber += 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (allowSkip) {
|
|
|
|
if (!new RegExp(expectationLine).hasMatch(outputLine)) {
|
|
|
|
outputLineNumber += 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
allowSkip = false;
|
|
|
|
}
|
2017-01-10 19:31:24 +00:00
|
|
|
if (expectationLine == '<<stderr>>') {
|
|
|
|
expect(haveSeenStdErrMarker, isFalse);
|
|
|
|
haveSeenStdErrMarker = true;
|
|
|
|
}
|
2017-02-23 23:08:25 +00:00
|
|
|
expect(outputLine, matches(expectationLine), reason: 'Full output:\n- - - -----8<----- - - -\n${output.join("\n")}\n- - - -----8<----- - - -');
|
2016-05-16 19:53:13 +00:00
|
|
|
expectationLineNumber += 1;
|
|
|
|
outputLineNumber += 1;
|
|
|
|
}
|
|
|
|
expect(allowSkip, isFalse);
|
2017-01-10 19:31:24 +00:00
|
|
|
if (!haveSeenStdErrMarker)
|
|
|
|
expect(exec.stderr, '');
|
2016-05-16 19:53:13 +00:00
|
|
|
}
|
2017-06-30 00:26:19 +00:00
|
|
|
|
2017-08-04 23:33:38 +00:00
|
|
|
Future<ProcessResult> _runFlutterTest(
|
|
|
|
String testName,
|
|
|
|
String workingDirectory,
|
|
|
|
String testDirectory, {
|
|
|
|
List<String> extraArgs: const <String>[],
|
|
|
|
}) async {
|
|
|
|
|
2017-06-30 00:26:19 +00:00
|
|
|
final String testFilePath = fs.path.join(testDirectory, '${testName}_test.dart');
|
|
|
|
final File testFile = fs.file(testFilePath);
|
|
|
|
if (!testFile.existsSync())
|
2017-08-04 23:33:38 +00:00
|
|
|
fail('missing test file: $testFile');
|
2017-06-30 00:26:19 +00:00
|
|
|
|
2017-11-08 21:59:49 +00:00
|
|
|
final List<String> args = <String>[]
|
|
|
|
..addAll(dartVmFlags)
|
|
|
|
..add(fs.path.absolute(fs.path.join('bin', 'flutter_tools.dart')))
|
|
|
|
..add('test')
|
|
|
|
..add('--no-color')
|
|
|
|
..addAll(extraArgs)
|
|
|
|
..add(testFilePath);
|
2017-06-30 00:26:19 +00:00
|
|
|
|
|
|
|
while (_testExclusionLock != null)
|
|
|
|
await _testExclusionLock;
|
|
|
|
|
|
|
|
final Completer<Null> testExclusionCompleter = new Completer<Null>();
|
|
|
|
_testExclusionLock = testExclusionCompleter.future;
|
|
|
|
try {
|
|
|
|
return await Process.run(
|
|
|
|
fs.path.join(dartSdkPath, 'bin', 'dart'),
|
|
|
|
args,
|
|
|
|
workingDirectory: workingDirectory,
|
|
|
|
);
|
|
|
|
} finally {
|
|
|
|
_testExclusionLock = null;
|
|
|
|
testExclusionCompleter.complete();
|
|
|
|
}
|
|
|
|
}
|