mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
Record/replay test infrastructure. (#8597)
This adds the test harness for record/replay tests.
This commit is contained in:
parent
5e2d3e956a
commit
3d079414ad
|
@ -146,8 +146,8 @@ Future<int> run(List<String> args, List<FlutterCommand> subCommands, {
|
|||
await _exit(0);
|
||||
runCompleter.complete(0);
|
||||
}, onError: (dynamic error, Chain chain) {
|
||||
flutterVersion ??= FlutterVersion.getVersionString();
|
||||
_handleToolError(error, chain, verbose, args, reportCrashes, flutterVersion)
|
||||
String getVersion() => flutterVersion ?? FlutterVersion.getVersionString();
|
||||
_handleToolError(error, chain, verbose, args, reportCrashes, getVersion)
|
||||
.then(runCompleter.complete, onError: runCompleter.completeError);
|
||||
});
|
||||
return runCompleter.future;
|
||||
|
@ -160,7 +160,7 @@ Future<int> _handleToolError(
|
|||
bool verbose,
|
||||
List<String> args,
|
||||
bool reportCrashes,
|
||||
String flutterVersion,
|
||||
String getFlutterVersion(),
|
||||
) async {
|
||||
if (error is UsageException) {
|
||||
stderr.writeln(error.message);
|
||||
|
@ -208,7 +208,7 @@ Future<int> _handleToolError(
|
|||
await CrashReportSender.instance.sendReport(
|
||||
error: error,
|
||||
stackTrace: chain,
|
||||
flutterVersion: flutterVersion,
|
||||
flutterVersion: getFlutterVersion(),
|
||||
);
|
||||
try {
|
||||
final File file = await _createLocalCrashReport(args, error, chain);
|
||||
|
|
|
@ -166,6 +166,13 @@ class BufferLogger extends Logger {
|
|||
printStatus(message);
|
||||
return new Status();
|
||||
}
|
||||
|
||||
/// Clears all buffers.
|
||||
void clear() {
|
||||
_error.clear();
|
||||
_status.clear();
|
||||
_trace.clear();
|
||||
}
|
||||
}
|
||||
|
||||
class VerboseLogger extends Logger {
|
||||
|
|
61
packages/flutter_tools/test/replay/common.dart
Normal file
61
packages/flutter_tools/test/replay/common.dart
Normal file
|
@ -0,0 +1,61 @@
|
|||
// 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';
|
||||
|
||||
import 'package:flutter_tools/executable.dart' as tools;
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
|
||||
/// Runs the specified [testMethod] in a minimal `AppContext` that is set up
|
||||
/// to redirect log output to a `BufferLogger` to avoid spamming `stdout`.
|
||||
///
|
||||
/// Test methods will generally want to use [expectProcessExits] in their method
|
||||
/// bodies.
|
||||
void testReplay(
|
||||
String description,
|
||||
dynamic testMethod(), {
|
||||
Timeout timeout,
|
||||
Map<Type, Generator> overrides: const <Type, Generator>{},
|
||||
bool skip,
|
||||
}) {
|
||||
setUp(() {
|
||||
setExitFunctionForTests();
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
restoreExitFunction();
|
||||
});
|
||||
|
||||
testUsingContext(
|
||||
description,
|
||||
testMethod,
|
||||
timeout: timeout,
|
||||
overrides: overrides,
|
||||
skip: skip,
|
||||
initializeContext: (_) {},
|
||||
);
|
||||
}
|
||||
|
||||
/// Expects that the specified [command] to Flutter tools exits with the
|
||||
/// specified [exitCode] (defaults to zero). It is expected that callers will
|
||||
/// be running in a test via [testReplay].
|
||||
///
|
||||
/// [command] should be the list of arguments that are passed to the `flutter`
|
||||
/// command-line tool. For example:
|
||||
///
|
||||
/// ```
|
||||
/// <String>[
|
||||
/// 'run',
|
||||
/// '--no-hot',
|
||||
/// '--no-resident',
|
||||
/// ]
|
||||
/// ```
|
||||
void expectProcessExits(List<String> command, {dynamic exitCode: 0}) {
|
||||
final Future<Null> mainFuture = tools.main(command);
|
||||
expect(mainFuture, throwsProcessExit(exitCode));
|
||||
}
|
|
@ -74,7 +74,7 @@ void testUsingContext(String description, dynamic testMethod(), {
|
|||
final String flutterRoot = getFlutterRoot();
|
||||
|
||||
try {
|
||||
return await testContext.runInZone(() {
|
||||
return await testContext.runInZone(() async {
|
||||
// Apply the overrides to the test context in the zone since their
|
||||
// instantiation may reference items already stored on the context.
|
||||
overrides.forEach((Type type, dynamic value()) {
|
||||
|
@ -83,23 +83,28 @@ void testUsingContext(String description, dynamic testMethod(), {
|
|||
// Provide a sane default for the flutterRoot directory. Individual
|
||||
// tests can override this.
|
||||
Cache.flutterRoot = flutterRoot;
|
||||
return testMethod();
|
||||
return await testMethod();
|
||||
}, onError: (dynamic error, StackTrace stackTrace) {
|
||||
_printBufferedErrors(testContext);
|
||||
throw error;
|
||||
});
|
||||
} catch (error) {
|
||||
if (testContext[Logger] is BufferLogger) {
|
||||
final BufferLogger bufferLogger = testContext[Logger];
|
||||
if (bufferLogger.errorText.isNotEmpty)
|
||||
print(bufferLogger.errorText);
|
||||
}
|
||||
// Previously the following line read "throw error;". This is bad because
|
||||
// it drops the error's actual stacktrace. Use 'rethrow' to preserve
|
||||
// the stacktrace.
|
||||
_printBufferedErrors(testContext);
|
||||
rethrow;
|
||||
}
|
||||
|
||||
}, timeout: timeout, skip: skip);
|
||||
}
|
||||
|
||||
void _printBufferedErrors(AppContext testContext) {
|
||||
if (testContext[Logger] is BufferLogger) {
|
||||
final BufferLogger bufferLogger = testContext[Logger];
|
||||
if (bufferLogger.errorText.isNotEmpty)
|
||||
print(bufferLogger.errorText);
|
||||
bufferLogger.clear();
|
||||
}
|
||||
}
|
||||
|
||||
String getFlutterRoot() {
|
||||
Error invalidScript() => new StateError('Invalid script: ${platform.script}');
|
||||
|
||||
|
|
Loading…
Reference in a new issue