Todd Volkert | 60b19b2 | 2016-11-30 08:42:42 -0800 | [diff] [blame] | 1 | // 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 | |
| 5 | import 'dart:async'; |
Todd Volkert | 60b19b2 | 2016-11-30 08:42:42 -0800 | [diff] [blame] | 6 | |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 7 | import 'package:process/process.dart'; |
| 8 | import 'package:process/record_replay.dart'; |
Todd Volkert | c9e7782 | 2016-12-02 13:39:54 -0800 | [diff] [blame] | 9 | |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 10 | import 'common.dart'; |
Todd Volkert | 60b19b2 | 2016-11-30 08:42:42 -0800 | [diff] [blame] | 11 | import 'context.dart'; |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 12 | import 'file_system.dart'; |
Todd Volkert | c9e7782 | 2016-12-02 13:39:54 -0800 | [diff] [blame] | 13 | import 'process.dart'; |
Todd Volkert | 60b19b2 | 2016-11-30 08:42:42 -0800 | [diff] [blame] | 14 | |
Todd Volkert | 9c05c34 | 2017-02-13 13:59:29 -0800 | [diff] [blame] | 15 | const String _kRecordingType = 'process'; |
Todd Volkert | 83d411f | 2017-03-10 09:39:01 -0800 | [diff] [blame] | 16 | const ProcessManager _kLocalProcessManager = const LocalProcessManager(); |
Todd Volkert | 9c05c34 | 2017-02-13 13:59:29 -0800 | [diff] [blame] | 17 | |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 18 | /// The active process manager. |
Todd Volkert | 83d411f | 2017-03-10 09:39:01 -0800 | [diff] [blame] | 19 | ProcessManager get processManager { |
| 20 | return context == null |
| 21 | ? _kLocalProcessManager |
| 22 | : context[ProcessManager]; |
| 23 | } |
Todd Volkert | 60b19b2 | 2016-11-30 08:42:42 -0800 | [diff] [blame] | 24 | |
Todd Volkert | 9c05c34 | 2017-02-13 13:59:29 -0800 | [diff] [blame] | 25 | /// Enables recording of process invocation activity to the specified base |
| 26 | /// recording [location]. |
Todd Volkert | 7536404 | 2016-12-06 10:09:00 -0800 | [diff] [blame] | 27 | /// |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 28 | /// This sets the [active process manager](processManager) to one that records |
| 29 | /// all process activity before delegating to a [LocalProcessManager]. |
Todd Volkert | 7536404 | 2016-12-06 10:09:00 -0800 | [diff] [blame] | 30 | /// |
Todd Volkert | 9c05c34 | 2017-02-13 13:59:29 -0800 | [diff] [blame] | 31 | /// 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 Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 35 | void enableRecordingProcessManager(String location) { |
Chris Bracken | 7a09316 | 2017-03-03 17:50:46 -0800 | [diff] [blame] | 36 | 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 Volkert | f60410f | 2017-02-27 15:38:47 -0800 | [diff] [blame] | 40 | addShutdownHook(() async { |
| 41 | await manager.flush(finishRunningProcesses: true); |
| 42 | context.setVariable(ProcessManager, originalProcessManager); |
| 43 | }, ShutdownStage.SERIALIZE_RECORDING); |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 44 | context.setVariable(ProcessManager, manager); |
| 45 | } |
Todd Volkert | 7536404 | 2016-12-06 10:09:00 -0800 | [diff] [blame] | 46 | |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 47 | /// 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 Volkert | 9c05c34 | 2017-02-13 13:59:29 -0800 | [diff] [blame] | 54 | /// [enableRecordingProcessManager]), or a [ToolExit] will be thrown. |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 55 | Future<Null> enableReplayProcessManager(String location) async { |
Chris Bracken | 7a09316 | 2017-03-03 17:50:46 -0800 | [diff] [blame] | 56 | final Directory dir = getReplaySource(location, _kRecordingType); |
Todd Volkert | 7536404 | 2016-12-06 10:09:00 -0800 | [diff] [blame] | 57 | |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 58 | 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 Volkert | 7536404 | 2016-12-06 10:09:00 -0800 | [diff] [blame] | 67 | ); |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 68 | } on ArgumentError catch (error) { |
| 69 | throwToolExit('Invalid replay-from: $error'); |
Todd Volkert | 7536404 | 2016-12-06 10:09:00 -0800 | [diff] [blame] | 70 | } |
| 71 | |
Todd Volkert | 03d163c | 2017-01-23 09:46:38 -0800 | [diff] [blame] | 72 | context.setVariable(ProcessManager, manager); |
Todd Volkert | 7536404 | 2016-12-06 10:09:00 -0800 | [diff] [blame] | 73 | } |