Unverified Commit 99866f4a authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Make timeout durations configurable (#30053)

parent 4b365fb9
......@@ -277,7 +277,7 @@ class AndroidDevice extends Device {
if (!await _checkForSupportedAdbVersion() || !await _checkForSupportedAndroidVersion())
return false;
final Status status = logger.startProgress('Installing ${fs.path.relative(apk.file.path)}...', timeout: kSlowOperation);
final Status status = logger.startProgress('Installing ${fs.path.relative(apk.file.path)}...', timeout: timeoutConfiguration.slowOperation);
final RunResult installResult = await runAsync(adbCommandForDevice(<String>['install', '-t', '-r', apk.file.path]));
status.stop();
// Some versions of adb exit with exit code 0 even on failure :(
......
......@@ -115,7 +115,7 @@ Future<GradleProject> _gradleProject() async {
/// Runs `gradlew dependencies`, ensuring that dependencies are resolved and
/// potentially downloaded.
Future<void> checkGradleDependencies() async {
final Status progress = logger.startProgress('Ensuring gradle dependencies are up to date...', timeout: kSlowOperation);
final Status progress = logger.startProgress('Ensuring gradle dependencies are up to date...', timeout: timeoutConfiguration.slowOperation);
final FlutterProject flutterProject = await FlutterProject.current();
final String gradle = await _ensureGradle(flutterProject);
await runCheckedAsync(
......@@ -133,7 +133,7 @@ Future<GradleProject> _readGradleProject() async {
final FlutterProject flutterProject = await FlutterProject.current();
final String gradle = await _ensureGradle(flutterProject);
updateLocalProperties(project: flutterProject);
final Status status = logger.startProgress('Resolving dependencies...', timeout: kSlowOperation);
final Status status = logger.startProgress('Resolving dependencies...', timeout: timeoutConfiguration.slowOperation);
GradleProject project;
try {
final RunResult propertiesRunResult = await runCheckedAsync(
......@@ -211,7 +211,7 @@ Future<String> _ensureGradle(FlutterProject project) async {
// of validating the Gradle executable. This may take several seconds.
Future<String> _initializeGradle(FlutterProject project) async {
final Directory android = project.android.hostAppGradleRoot;
final Status status = logger.startProgress('Initializing gradle...', timeout: kSlowOperation);
final Status status = logger.startProgress('Initializing gradle...', timeout: timeoutConfiguration.slowOperation);
String gradle = _locateGradlewExecutable(android);
if (gradle == null) {
injectGradleWrapper(android);
......@@ -351,7 +351,7 @@ Future<void> _buildGradleProjectV1(FlutterProject project, String gradle) async
// Run 'gradlew build'.
final Status status = logger.startProgress(
'Running \'gradlew build\'...',
timeout: kSlowOperation,
timeout: timeoutConfiguration.slowOperation,
multilineOutput: true,
);
final int exitCode = await runCommandAndStreamOutput(
......@@ -403,7 +403,7 @@ Future<void> _buildGradleProjectV2(
}
final Status status = logger.startProgress(
'Running Gradle task \'$assembleTask\'...',
timeout: kSlowOperation,
timeout: timeoutConfiguration.slowOperation,
multilineOutput: true,
);
final String gradlePath = fs.file(gradle).absolute.path;
......
......@@ -13,8 +13,29 @@ import 'terminal.dart';
import 'utils.dart';
const int kDefaultStatusPadding = 59;
const Duration kFastOperation = Duration(seconds: 2);
const Duration kSlowOperation = Duration(minutes: 2);
const Duration _kFastOperation = Duration(seconds: 2);
const Duration _kSlowOperation = Duration(minutes: 2);
/// The [TimeoutConfiguration] instance.
///
/// If not provided via injection, a default instance is provided.
TimeoutConfiguration get timeoutConfiguration => context[TimeoutConfiguration] ?? const TimeoutConfiguration();
class TimeoutConfiguration {
const TimeoutConfiguration();
/// The expected time that various "slow" operations take, such as running
/// the analyzer.
///
/// Defaults to 2 minutes.
Duration get slowOperation => _kSlowOperation;
/// The expected time that various "fast" operations take, such as a hot
/// reload.
///
/// Defaults to 2 seconds.
Duration get fastOperation => _kFastOperation;
}
typedef VoidCallback = void Function();
......@@ -375,7 +396,7 @@ class VerboseLogger extends Logger {
timeout: timeout,
onFinish: () {
String time;
if (timeout == null || timeout > kFastOperation) {
if (timeout == null || timeout > timeoutConfiguration.fastOperation) {
time = getElapsedAsSeconds(timer.elapsed);
} else {
time = getElapsedAsMilliseconds(timer.elapsed);
......@@ -473,7 +494,7 @@ abstract class Status {
@protected
String get elapsedTime {
if (timeout == null || timeout > kFastOperation)
if (timeout == null || timeout > timeoutConfiguration.fastOperation)
return getElapsedAsSeconds(_stopwatch.elapsed);
return getElapsedAsMilliseconds(_stopwatch.elapsed);
}
......
......@@ -366,7 +366,7 @@ abstract class CachedArtifact {
Future<void> _downloadArchive(String message, Uri url, Directory location, bool verifier(File f), void extractor(File f, Directory d)) {
return _withDownloadFile('${flattenNameSubdirs(url)}', (File tempFile) async {
if (!verifier(tempFile)) {
final Status status = logger.startProgress(message, timeout: kSlowOperation);
final Status status = logger.startProgress(message, timeout: timeoutConfiguration.slowOperation);
try {
await _downloadFile(url, tempFile);
status.stop();
......@@ -781,7 +781,7 @@ Future<void> _downloadFile(Uri url, File location) async {
}
Future<bool> _doesRemoteExist(String message, Uri url) async {
final Status status = logger.startProgress(message, timeout: kSlowOperation);
final Status status = logger.startProgress(message, timeout: timeoutConfiguration.slowOperation);
final bool exists = await doesRemoteFileExist(url);
status.stop();
return exists;
......
......@@ -77,7 +77,7 @@ class AnalyzeContinuously extends AnalyzeBase {
analysisStatus?.cancel();
if (!firstAnalysis)
printStatus('\n');
analysisStatus = logger.startProgress('Analyzing $analysisTarget...', timeout: kSlowOperation);
analysisStatus = logger.startProgress('Analyzing $analysisTarget...', timeout: timeoutConfiguration.slowOperation);
analyzedPaths.clear();
analysisTimer = Stopwatch()..start();
} else {
......
......@@ -107,7 +107,7 @@ class AnalyzeOnce extends AnalyzeBase {
? '${directories.length} ${directories.length == 1 ? 'directory' : 'directories'}'
: fs.path.basename(directories.first);
final Status progress = argResults['preamble']
? logger.startProgress('Analyzing $message...', timeout: kSlowOperation)
? logger.startProgress('Analyzing $message...', timeout: timeoutConfiguration.slowOperation)
: null;
await analysisCompleter.future;
......
......@@ -69,7 +69,7 @@ class BuildAotCommand extends BuildSubCommand {
final String typeName = artifacts.getEngineType(platform, buildMode);
status = logger.startProgress(
'Building AOT snapshot in ${getFriendlyModeName(getBuildMode())} mode ($typeName)...',
timeout: kSlowOperation,
timeout: timeoutConfiguration.slowOperation,
);
}
final String outputPath = argResults['output-dir'] ?? getAotBuildDirectory();
......
......@@ -87,7 +87,7 @@ class UpdatePackagesCommand extends FlutterCommand {
Future<void> _downloadCoverageData() async {
final Status status = logger.startProgress(
'Downloading lcov data for package:flutter...',
timeout: kSlowOperation,
timeout: timeoutConfiguration.slowOperation,
);
final String urlBase = platform.environment['FLUTTER_STORAGE_BASE_URL'] ?? 'https://storage.googleapis.com';
final List<int> data = await fetchUrl(Uri.parse('$urlBase/flutter_infra/flutter/coverage/lcov.info'));
......
......@@ -91,6 +91,7 @@ Future<T> runInContext<T>(
SimControl: () => SimControl(),
SystemClock: () => const SystemClock(),
Stdio: () => const Stdio(),
TimeoutConfiguration: () => const TimeoutConfiguration(),
Usage: () => Usage(),
UserMessages: () => UserMessages(),
WindowsWorkflow: () => const WindowsWorkflow(),
......
......@@ -93,7 +93,7 @@ Future<void> pubGet({
final String command = upgrade ? 'upgrade' : 'get';
final Status status = logger.startProgress(
'Running "flutter packages $command" in ${fs.path.basename(directory)}...',
timeout: kSlowOperation,
timeout: timeoutConfiguration.slowOperation,
);
final List<String> args = <String>['--verbosity=warning'];
if (FlutterCommand.current != null && FlutterCommand.current.globalResults['verbose'])
......
......@@ -187,7 +187,7 @@ class Doctor {
for (ValidatorTask validatorTask in startValidatorTasks()) {
final DoctorValidator validator = validatorTask.validator;
final Status status = Status.withSpinner(
timeout: kFastOperation,
timeout: timeoutConfiguration.fastOperation,
slowWarningCallback: () => validator.slowWarning,
);
ValidationResult result;
......
......@@ -254,7 +254,7 @@ class CocoaPods {
}
Future<void> _runPodInstall(IosProject iosProject, String engineDirectory) async {
final Status status = logger.startProgress('Running pod install...', timeout: kSlowOperation);
final Status status = logger.startProgress('Running pod install...', timeout: timeoutConfiguration.slowOperation);
final ProcessResult result = await processManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: iosProject.hostAppRoot.path,
......
......@@ -309,7 +309,7 @@ class IOSDevice extends Device {
int installationResult = -1;
Uri localObservatoryUri;
final Status installStatus = logger.startProgress('Installing and launching...', timeout: kSlowOperation);
final Status installStatus = logger.startProgress('Installing and launching...', timeout: timeoutConfiguration.slowOperation);
if (!debuggingOptions.debuggingEnabled) {
// If debugging is not enabled, just launch the application and continue.
......
......@@ -480,7 +480,7 @@ Future<XcodeBuildResult> buildXcodeProject({
initialBuildStatus = null;
buildSubStatus = logger.startProgress(
line,
timeout: kSlowOperation,
timeout: timeoutConfiguration.slowOperation,
progressIndicatorPadding: kDefaultStatusPadding - 7,
);
}
......@@ -495,7 +495,7 @@ Future<XcodeBuildResult> buildXcodeProject({
}
final Stopwatch buildStopwatch = Stopwatch()..start();
initialBuildStatus = logger.startProgress('Running Xcode build...', timeout: kFastOperation);
initialBuildStatus = logger.startProgress('Running Xcode build...', timeout: timeoutConfiguration.fastOperation);
final RunResult buildResult = await runAsync(
buildCommands,
workingDirectory: app.project.hostAppRoot.path,
......
......@@ -447,7 +447,7 @@ class FlutterDevice {
}) async {
final Status devFSStatus = logger.startProgress(
'Syncing files to device ${device.name}...',
timeout: kFastOperation,
timeout: timeoutConfiguration.fastOperation,
);
UpdateFSReport report;
try {
......@@ -633,7 +633,7 @@ abstract class ResidentRunner {
}
Future<void> _screenshot(FlutterDevice device) async {
final Status status = logger.startProgress('Taking screenshot for ${device.device.name}...', timeout: kFastOperation);
final Status status = logger.startProgress('Taking screenshot for ${device.device.name}...', timeout: timeoutConfiguration.fastOperation);
final File outputFile = getUniqueFile(fs.currentDirectory, 'flutter', 'png');
try {
if (supportsServiceProtocol && isRunningDebug) {
......
......@@ -538,7 +538,7 @@ class HotRunner extends ResidentRunner {
}
final Status status = logger.startProgress(
'Performing hot restart...',
timeout: kFastOperation,
timeout: timeoutConfiguration.fastOperation,
progressId: 'hot.restart',
);
try {
......@@ -557,7 +557,7 @@ class HotRunner extends ResidentRunner {
final String progressPrefix = reloadOnTopOfSnapshot ? 'Initializing' : 'Performing';
Status status = logger.startProgress(
'$progressPrefix hot reload...',
timeout: kFastOperation,
timeout: timeoutConfiguration.fastOperation,
progressId: 'hot.reload',
);
OperationResult result;
......@@ -570,7 +570,7 @@ class HotRunner extends ResidentRunner {
status?.cancel();
status = logger.startProgress(
message,
timeout: kSlowOperation,
timeout: timeoutConfiguration.slowOperation,
progressId: 'hot.reload',
);
showTime = false;
......
......@@ -92,7 +92,7 @@ class CoverageCollector extends TestWatcher {
}
Future<bool> collectCoverageData(String coveragePath, { bool mergeCoverageData = false, Directory coverageDirectory }) async {
final Status status = logger.startProgress('Collecting coverage information...', timeout: kFastOperation);
final Status status = logger.startProgress('Collecting coverage information...', timeout: timeoutConfiguration.fastOperation);
final String coverageData = await finalizeCoverage(
coverageDirectory: coverageDirectory,
);
......
......@@ -40,7 +40,7 @@ class Tracing {
if (awaitFirstFrame) {
final Status status = logger.startProgress(
'Waiting for application to render first frame...',
timeout: kFastOperation,
timeout: timeoutConfiguration.fastOperation,
);
try {
final Completer<void> whenFirstFrameRendered = Completer<void>();
......
......@@ -166,7 +166,7 @@ void main() {
final Status status = logger.startProgress(
'Hello',
progressId: null,
timeout: kSlowOperation,
timeout: timeoutConfiguration.slowOperation,
progressIndicatorPadding: 20, // this minus the "Hello" equals the 15 below.
);
expect(outputStderr().length, equals(1));
......@@ -357,7 +357,7 @@ void main() {
called = 0;
summaryStatus = SummaryStatus(
message: 'Hello world',
timeout: kSlowOperation,
timeout: timeoutConfiguration.slowOperation,
padding: 20,
onFinish: () => called++,
);
......@@ -593,7 +593,7 @@ void main() {
final Status status = logger.startProgress(
'Hello',
progressId: null,
timeout: kSlowOperation,
timeout: timeoutConfiguration.slowOperation,
progressIndicatorPadding: 20, // this minus the "Hello" equals the 15 below.
);
expect(outputStderr().length, equals(1));
......@@ -661,8 +661,8 @@ void main() {
testUsingContext('sequential startProgress calls with StdoutLogger', () async {
final Logger logger = context[Logger];
logger.startProgress('AAA', timeout: kFastOperation)..stop();
logger.startProgress('BBB', timeout: kFastOperation)..stop();
logger.startProgress('AAA', timeout: timeoutConfiguration.fastOperation)..stop();
logger.startProgress('BBB', timeout: timeoutConfiguration.fastOperation)..stop();
final List<String> output = outputStdout();
expect(output.length, equals(3));
// There's 61 spaces at the start: 59 (padding default) - 3 (length of AAA) + 5 (margin).
......@@ -679,8 +679,8 @@ void main() {
testUsingContext('sequential startProgress calls with VerboseLogger and StdoutLogger', () async {
final Logger logger = context[Logger];
logger.startProgress('AAA', timeout: kFastOperation)..stop();
logger.startProgress('BBB', timeout: kFastOperation)..stop();
logger.startProgress('AAA', timeout: timeoutConfiguration.fastOperation)..stop();
logger.startProgress('BBB', timeout: timeoutConfiguration.fastOperation)..stop();
expect(outputStdout(), <Matcher>[
matches(r'^\[ (?: {0,2}\+[0-9]{1,3} ms| )\] AAA$'),
matches(r'^\[ (?: {0,2}\+[0-9]{1,3} ms| )\] AAA \(completed.*\)$'),
......@@ -696,8 +696,8 @@ void main() {
testUsingContext('sequential startProgress calls with BufferLogger', () async {
final BufferLogger logger = context[Logger];
logger.startProgress('AAA', timeout: kFastOperation)..stop();
logger.startProgress('BBB', timeout: kFastOperation)..stop();
logger.startProgress('AAA', timeout: timeoutConfiguration.fastOperation)..stop();
logger.startProgress('BBB', timeout: timeoutConfiguration.fastOperation)..stop();
expect(logger.statusText, 'AAA\nBBB\n');
}, overrides: <Type, Generator>{
Logger: () => BufferLogger(),
......
......@@ -86,6 +86,7 @@ void testUsingContext(
Usage: () => MockUsage(),
XcodeProjectInterpreter: () => MockXcodeProjectInterpreter(),
FileSystem: () => LocalFileSystemBlockingSetCurrentDirectory(),
TimeoutConfiguration: () => const TimeoutConfiguration(),
},
body: () {
final String flutterRoot = getFlutterRoot();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment