blob: 447a3baba5f568f27c24e6526203f6ed6facb2f2 [file] [log] [blame]
Todd Volkert60b19b22016-11-30 08:42:42 -08001// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'dart:async';
Todd Volkert60b19b22016-11-30 08:42:42 -08006
Todd Volkert03d163c2017-01-23 09:46:38 -08007import 'package:process/process.dart';
8import 'package:process/record_replay.dart';
Todd Volkertc9e77822016-12-02 13:39:54 -08009
Todd Volkert03d163c2017-01-23 09:46:38 -080010import 'common.dart';
Todd Volkert60b19b22016-11-30 08:42:42 -080011import 'context.dart';
Todd Volkert03d163c2017-01-23 09:46:38 -080012import 'file_system.dart';
Todd Volkertc9e77822016-12-02 13:39:54 -080013import 'process.dart';
Todd Volkert60b19b22016-11-30 08:42:42 -080014
Todd Volkert9c05c342017-02-13 13:59:29 -080015const String _kRecordingType = 'process';
Todd Volkert83d411f2017-03-10 09:39:01 -080016const ProcessManager _kLocalProcessManager = const LocalProcessManager();
Todd Volkert9c05c342017-02-13 13:59:29 -080017
Todd Volkert03d163c2017-01-23 09:46:38 -080018/// The active process manager.
Todd Volkert83d411f2017-03-10 09:39:01 -080019ProcessManager get processManager {
20 return context == null
21 ? _kLocalProcessManager
22 : context[ProcessManager];
23}
Todd Volkert60b19b22016-11-30 08:42:42 -080024
Todd Volkert9c05c342017-02-13 13:59:29 -080025/// Enables recording of process invocation activity to the specified base
26/// recording [location].
Todd Volkert75364042016-12-06 10:09:00 -080027///
Todd Volkert03d163c2017-01-23 09:46:38 -080028/// This sets the [active process manager](processManager) to one that records
29/// all process activity before delegating to a [LocalProcessManager].
Todd Volkert75364042016-12-06 10:09:00 -080030///
Todd Volkert9c05c342017-02-13 13:59:29 -080031/// Activity will be recorded in a subdirectory of [location] named `"process"`.
32/// It is permissible for [location] to represent an existing non-empty
33/// directory as long as there is no collision with the `"process"`
34/// subdirectory.
Todd Volkert03d163c2017-01-23 09:46:38 -080035void enableRecordingProcessManager(String location) {
Chris Bracken7a093162017-03-03 17:50:46 -080036 final ProcessManager originalProcessManager = processManager;
37 final Directory dir = getRecordingSink(location, _kRecordingType);
38 final ProcessManager delegate = const LocalProcessManager();
39 final RecordingProcessManager manager = new RecordingProcessManager(delegate, dir);
Todd Volkertf60410f2017-02-27 15:38:47 -080040 addShutdownHook(() async {
41 await manager.flush(finishRunningProcesses: true);
42 context.setVariable(ProcessManager, originalProcessManager);
43 }, ShutdownStage.SERIALIZE_RECORDING);
Todd Volkert03d163c2017-01-23 09:46:38 -080044 context.setVariable(ProcessManager, manager);
45}
Todd Volkert75364042016-12-06 10:09:00 -080046
Todd Volkert03d163c2017-01-23 09:46:38 -080047/// Enables process invocation replay mode.
48///
49/// This sets the [active process manager](processManager) to one that replays
50/// process activity from a previously recorded set of invocations.
51///
52/// [location] must represent a directory to which process activity has been
53/// recorded (i.e. the result of having been previously passed to
Todd Volkert9c05c342017-02-13 13:59:29 -080054/// [enableRecordingProcessManager]), or a [ToolExit] will be thrown.
Todd Volkert03d163c2017-01-23 09:46:38 -080055Future<Null> enableReplayProcessManager(String location) async {
Chris Bracken7a093162017-03-03 17:50:46 -080056 final Directory dir = getReplaySource(location, _kRecordingType);
Todd Volkert75364042016-12-06 10:09:00 -080057
Todd Volkert03d163c2017-01-23 09:46:38 -080058 ProcessManager manager;
59 try {
60 manager = await ReplayProcessManager.create(dir,
61 // TODO(tvolkert): Once https://github.com/flutter/flutter/issues/7166 is
62 // resolved, we can use the default `streamDelay`. In the
63 // meantime, native file I/O operations cause our `tail` process
64 // streams to flush before our protocol discovery is listening on
65 // them, causing us to timeout waiting for the observatory port.
66 streamDelay: const Duration(milliseconds: 50),
Todd Volkert75364042016-12-06 10:09:00 -080067 );
Todd Volkert03d163c2017-01-23 09:46:38 -080068 } on ArgumentError catch (error) {
69 throwToolExit('Invalid replay-from: $error');
Todd Volkert75364042016-12-06 10:09:00 -080070 }
71
Todd Volkert03d163c2017-01-23 09:46:38 -080072 context.setVariable(ProcessManager, manager);
Todd Volkert75364042016-12-06 10:09:00 -080073}