blob: 8c318bc8c6dc080a5b0a37cad2c21ba236119091 [file] [log] [blame]
Adam Barthbdd20662015-10-11 19:42:50 -07001// Copyright 2015 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
John McCutchan9cb70012016-03-04 15:01:26 -08005import 'dart:async';
Chris Bracken538ba522018-01-24 17:16:30 -08006import 'dart:convert';
Jonah Williams5e77d652019-04-30 15:42:16 -07007import 'dart:io' as io show IOSink, ProcessSignal;
Devon Carew5ad6a572016-03-11 08:49:55 -08008
Devon Carew67046f92016-02-20 22:00:11 -08009import 'package:flutter_tools/src/android/android_device.dart';
Chris Bracken74478d12018-01-24 20:40:25 -080010import 'package:flutter_tools/src/android/android_sdk.dart' show AndroidSdk;
Adam Barthda0a12c2015-11-10 13:18:34 -080011import 'package:flutter_tools/src/application_package.dart';
Chris Bracken74478d12018-01-24 20:40:25 -080012import 'package:flutter_tools/src/base/file_system.dart' hide IOSink;
Chris Bracken538ba522018-01-24 17:16:30 -080013import 'package:flutter_tools/src/base/io.dart';
Dan Field15f21192019-02-23 09:56:57 -080014import 'package:flutter_tools/src/base/platform.dart';
Jason Simmonsa590ee22016-05-12 12:22:15 -070015import 'package:flutter_tools/src/build_info.dart';
Chris Bracken251e82d2018-08-31 13:31:56 -070016import 'package:flutter_tools/src/compile.dart';
Jonah Williams27876e02019-05-31 13:17:12 -070017import 'package:flutter_tools/src/devfs.dart';
Adam Barthda0a12c2015-11-10 13:18:34 -080018import 'package:flutter_tools/src/device.dart';
Devon Carew67046f92016-02-20 22:00:11 -080019import 'package:flutter_tools/src/ios/devices.dart';
20import 'package:flutter_tools/src/ios/simulators.dart';
Mikkel Nygaard Ravn22832d32018-08-30 16:18:44 +020021import 'package:flutter_tools/src/project.dart';
Adam Barth9662d492015-11-28 21:07:16 -080022import 'package:flutter_tools/src/runner/flutter_command.dart';
Todd Volkert5d297372017-03-10 13:53:22 -080023import 'package:mockito/mockito.dart';
Chris Bracken538ba522018-01-24 17:16:30 -080024import 'package:process/process.dart';
Ian Hickson686d8f82018-08-14 20:33:58 -070025
26import 'common.dart';
Adam Barthbdd20662015-10-11 19:42:50 -070027
28class MockApplicationPackageStore extends ApplicationPackageStore {
29 MockApplicationPackageStore() : super(
Alexandre Ardhuind927c932018-09-12 08:29:29 +020030 android: AndroidApk(
Adam Barthe2744e92016-03-11 12:48:12 -080031 id: 'io.flutter.android.mock',
Sigurd Meldgaard2d3a5c72018-07-20 08:00:30 +020032 file: fs.file('/mock/path/to/android/SkyShell.apk'),
Stanislav Baranov55f3da72018-12-19 16:27:47 -080033 versionCode: 1,
Alexandre Ardhuin387f8852019-03-01 08:17:55 +010034 launchActivity: 'io.flutter.android.mock.MockActivity',
Adam Barthe2744e92016-03-11 12:48:12 -080035 ),
Alexandre Ardhuind927c932018-09-12 08:29:29 +020036 iOS: BuildableIOSApp(MockIosProject())
Devon Carew3463d892016-02-22 12:37:08 -080037 );
Adam Barthbdd20662015-10-11 19:42:50 -070038}
39
Chris Bracken74478d12018-01-24 20:40:25 -080040/// An SDK installation with several SDK levels (19, 22, 23).
41class MockAndroidSdk extends Mock implements AndroidSdk {
42 static Directory createSdkDirectory({
Alexandre Ardhuin09276be2018-06-05 08:50:40 +020043 bool withAndroidN = false,
Chris Bracken74478d12018-01-24 20:40:25 -080044 String withNdkDir,
Vyacheslav Egorov8f65ee92019-01-16 21:30:37 +010045 int ndkVersion = 16,
Alexandre Ardhuin09276be2018-06-05 08:50:40 +020046 bool withNdkSysroot = false,
47 bool withSdkManager = true,
Dan Field15f21192019-02-23 09:56:57 -080048 bool withPlatformTools = true,
49 bool withBuildTools = true,
Chris Bracken74478d12018-01-24 20:40:25 -080050 }) {
Ian Hickson3dec6a62018-08-17 13:17:23 -070051 final Directory dir = fs.systemTempDirectory.createTempSync('flutter_mock_android_sdk.');
Dan Field15f21192019-02-23 09:56:57 -080052 final String exe = platform.isWindows ? '.exe' : '';
53 final String bat = platform.isWindows ? '.bat' : '';
Chris Bracken74478d12018-01-24 20:40:25 -080054
Dan Field15f21192019-02-23 09:56:57 -080055 _createDir(dir, 'licenses');
Chris Bracken74478d12018-01-24 20:40:25 -080056
Dan Field15f21192019-02-23 09:56:57 -080057 if (withPlatformTools) {
58 _createSdkFile(dir, 'platform-tools/adb$exe');
59 }
60
61 if (withBuildTools) {
62 _createSdkFile(dir, 'build-tools/19.1.0/aapt$exe');
63 _createSdkFile(dir, 'build-tools/22.0.1/aapt$exe');
64 _createSdkFile(dir, 'build-tools/23.0.2/aapt$exe');
65 if (withAndroidN)
66 _createSdkFile(dir, 'build-tools/24.0.0-preview/aapt$exe');
67 }
Chris Bracken74478d12018-01-24 20:40:25 -080068
69 _createSdkFile(dir, 'platforms/android-22/android.jar');
70 _createSdkFile(dir, 'platforms/android-23/android.jar');
71 if (withAndroidN) {
72 _createSdkFile(dir, 'platforms/android-N/android.jar');
73 _createSdkFile(dir, 'platforms/android-N/build.prop', contents: _buildProp);
74 }
75
76 if (withSdkManager)
Dan Field15f21192019-02-23 09:56:57 -080077 _createSdkFile(dir, 'tools/bin/sdkmanager$bat');
Chris Bracken74478d12018-01-24 20:40:25 -080078
79 if (withNdkDir != null) {
Vyacheslav Egorov8f65ee92019-01-16 21:30:37 +010080 final String ndkToolchainBin = fs.path.join(
Ian Hickson3dec6a62018-08-17 13:17:23 -070081 'ndk-bundle',
82 'toolchains',
83 'arm-linux-androideabi-4.9',
84 'prebuilt',
85 withNdkDir,
86 'bin',
Vyacheslav Egorov8f65ee92019-01-16 21:30:37 +010087 );
88 final String ndkCompiler = fs.path.join(
89 ndkToolchainBin,
Ian Hickson3dec6a62018-08-17 13:17:23 -070090 'arm-linux-androideabi-gcc',
91 );
Vyacheslav Egorov8f65ee92019-01-16 21:30:37 +010092 final String ndkLinker = fs.path.join(
93 ndkToolchainBin,
94 'arm-linux-androideabi-ld',
95 );
Chris Bracken74478d12018-01-24 20:40:25 -080096 _createSdkFile(dir, ndkCompiler);
Vyacheslav Egorov8f65ee92019-01-16 21:30:37 +010097 _createSdkFile(dir, ndkLinker);
98 _createSdkFile(dir, fs.path.join('ndk-bundle', 'source.properties'), contents: '''
99Pkg.Desc = Android NDK[]
100Pkg.Revision = $ndkVersion.1.5063045
101
102''');
Chris Bracken74478d12018-01-24 20:40:25 -0800103 }
104 if (withNdkSysroot) {
Ian Hickson3dec6a62018-08-17 13:17:23 -0700105 final String armPlatform = fs.path.join(
106 'ndk-bundle',
107 'platforms',
108 'android-9',
109 'arch-arm',
110 );
Chris Bracken74478d12018-01-24 20:40:25 -0800111 _createDir(dir, armPlatform);
112 }
113
114 return dir;
115 }
116
117 static void _createSdkFile(Directory dir, String filePath, { String contents }) {
118 final File file = dir.childFile(filePath);
119 file.createSync(recursive: true);
120 if (contents != null) {
121 file.writeAsStringSync(contents, flush: true);
122 }
123 }
124
125 static void _createDir(Directory dir, String path) {
126 final Directory directory = fs.directory(fs.path.join(dir.path, path));
127 directory.createSync(recursive: true);
128 }
129
130 static const String _buildProp = r'''
131ro.build.version.incremental=1624448
132ro.build.version.sdk=24
133ro.build.version.codename=REL
134''';
135}
136
Chris Bracken538ba522018-01-24 17:16:30 -0800137/// A strategy for creating Process objects from a list of commands.
Alexandre Ardhuina07d3712018-09-14 21:06:19 +0200138typedef ProcessFactory = Process Function(List<String> command);
Chris Bracken538ba522018-01-24 17:16:30 -0800139
140/// A ProcessManager that starts Processes by delegating to a ProcessFactory.
141class MockProcessManager implements ProcessManager {
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200142 ProcessFactory processFactory = (List<String> commands) => MockProcess();
Chris Brackend3705f32018-01-24 22:27:24 -0800143 bool succeed = true;
Chris Bracken538ba522018-01-24 17:16:30 -0800144 List<String> commands;
145
146 @override
Chris Brackend3705f32018-01-24 22:27:24 -0800147 bool canRun(dynamic command, { String workingDirectory }) => succeed;
148
149 @override
Chris Bracken538ba522018-01-24 17:16:30 -0800150 Future<Process> start(
151 List<dynamic> command, {
152 String workingDirectory,
153 Map<String, String> environment,
Alexandre Ardhuin09276be2018-06-05 08:50:40 +0200154 bool includeParentEnvironment = true,
155 bool runInShell = false,
Leaf Petersen32f94442018-07-20 15:07:24 -0700156 ProcessStartMode mode = ProcessStartMode.normal,
Chris Bracken538ba522018-01-24 17:16:30 -0800157 }) {
Chris Brackend3705f32018-01-24 22:27:24 -0800158 if (!succeed) {
159 final String executable = command[0];
160 final List<String> arguments = command.length > 1 ? command.sublist(1) : <String>[];
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200161 throw ProcessException(executable, arguments);
Chris Brackend3705f32018-01-24 22:27:24 -0800162 }
163
Chris Bracken538ba522018-01-24 17:16:30 -0800164 commands = command;
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200165 return Future<Process>.value(processFactory(command));
Chris Bracken538ba522018-01-24 17:16:30 -0800166 }
167
168 @override
169 dynamic noSuchMethod(Invocation invocation) => null;
170}
171
172/// A process that exits successfully with no output and ignores all input.
173class MockProcess extends Mock implements Process {
174 MockProcess({
Alexandre Ardhuin09276be2018-06-05 08:50:40 +0200175 this.pid = 1,
Chris Bracken538ba522018-01-24 17:16:30 -0800176 Future<int> exitCode,
177 Stream<List<int>> stdin,
Alexandre Ardhuin09276be2018-06-05 08:50:40 +0200178 this.stdout = const Stream<List<int>>.empty(),
179 this.stderr = const Stream<List<int>>.empty(),
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200180 }) : exitCode = exitCode ?? Future<int>.value(0),
181 stdin = stdin ?? MemoryIOSink();
Chris Bracken538ba522018-01-24 17:16:30 -0800182
183 @override
184 final int pid;
185
186 @override
187 final Future<int> exitCode;
188
189 @override
190 final io.IOSink stdin;
191
192 @override
193 final Stream<List<int>> stdout;
194
195 @override
196 final Stream<List<int>> stderr;
197}
198
Jonah Williams5e77d652019-04-30 15:42:16 -0700199/// A fake process implemenation which can be provided all necessary values.
200class FakeProcess implements Process {
201 FakeProcess({
202 this.pid = 1,
203 Future<int> exitCode,
204 Stream<List<int>> stdin,
205 this.stdout = const Stream<List<int>>.empty(),
206 this.stderr = const Stream<List<int>>.empty(),
207 }) : exitCode = exitCode ?? Future<int>.value(0),
208 stdin = stdin ?? MemoryIOSink();
209
210 @override
211 final int pid;
212
213 @override
214 final Future<int> exitCode;
215
216 @override
217 final io.IOSink stdin;
218
219 @override
220 final Stream<List<int>> stdout;
221
222 @override
223 final Stream<List<int>> stderr;
224
225 @override
226 bool kill([io.ProcessSignal signal = io.ProcessSignal.sigterm]) {
227 return true;
228 }
229}
230
Chris Bracken538ba522018-01-24 17:16:30 -0800231/// A process that prompts the user to proceed, then asynchronously writes
232/// some lines to stdout before it exits.
233class PromptingProcess implements Process {
Alexandre Ardhuin2d3ff102018-10-05 07:54:56 +0200234 Future<void> showPrompt(String prompt, List<String> outputLines) async {
Jason Simmons466d1542018-03-12 11:06:32 -0700235 _stdoutController.add(utf8.encode(prompt));
Chris Bracken538ba522018-01-24 17:16:30 -0800236 final List<int> bytesOnStdin = await _stdin.future;
237 // Echo stdin to stdout.
238 _stdoutController.add(bytesOnStdin);
Jason Simmons466d1542018-03-12 11:06:32 -0700239 if (bytesOnStdin[0] == utf8.encode('y')[0]) {
Chris Bracken538ba522018-01-24 17:16:30 -0800240 for (final String line in outputLines)
Jason Simmons466d1542018-03-12 11:06:32 -0700241 _stdoutController.add(utf8.encode('$line\n'));
Chris Bracken538ba522018-01-24 17:16:30 -0800242 }
243 await _stdoutController.close();
244 }
245
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200246 final StreamController<List<int>> _stdoutController = StreamController<List<int>>();
247 final CompleterIOSink _stdin = CompleterIOSink();
Chris Bracken538ba522018-01-24 17:16:30 -0800248
249 @override
250 Stream<List<int>> get stdout => _stdoutController.stream;
251
252 @override
253 Stream<List<int>> get stderr => const Stream<List<int>>.empty();
254
255 @override
256 IOSink get stdin => _stdin;
257
258 @override
259 Future<int> get exitCode async {
260 await _stdoutController.done;
261 return 0;
262 }
263
264 @override
265 dynamic noSuchMethod(Invocation invocation) => null;
266}
267
268/// An IOSink that completes a future with the first line written to it.
269class CompleterIOSink extends MemoryIOSink {
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200270 final Completer<List<int>> _completer = Completer<List<int>>();
Chris Bracken538ba522018-01-24 17:16:30 -0800271
272 Future<List<int>> get future => _completer.future;
273
274 @override
275 void add(List<int> data) {
276 if (!_completer.isCompleted)
277 _completer.complete(data);
278 super.add(data);
279 }
280}
281
282/// An IOSink that collects whatever is written to it.
283class MemoryIOSink implements IOSink {
284 @override
Jason Simmons466d1542018-03-12 11:06:32 -0700285 Encoding encoding = utf8;
Chris Bracken538ba522018-01-24 17:16:30 -0800286
287 final List<List<int>> writes = <List<int>>[];
288
289 @override
290 void add(List<int> data) {
291 writes.add(data);
292 }
293
294 @override
Alexandre Ardhuin2d3ff102018-10-05 07:54:56 +0200295 Future<void> addStream(Stream<List<int>> stream) {
296 final Completer<void> completer = Completer<void>();
Chris Bracken538ba522018-01-24 17:16:30 -0800297 stream.listen((List<int> data) {
298 add(data);
Alexandre Ardhuin2d3ff102018-10-05 07:54:56 +0200299 }).onDone(() => completer.complete());
Chris Bracken538ba522018-01-24 17:16:30 -0800300 return completer.future;
301 }
302
303 @override
304 void writeCharCode(int charCode) {
305 add(<int>[charCode]);
306 }
307
308 @override
309 void write(Object obj) {
310 add(encoding.encode('$obj'));
311 }
312
313 @override
Alexandre Ardhuin5169ab52019-02-21 09:27:07 +0100314 void writeln([ Object obj = '' ]) {
Chris Bracken538ba522018-01-24 17:16:30 -0800315 add(encoding.encode('$obj\n'));
316 }
317
318 @override
Alexandre Ardhuin5169ab52019-02-21 09:27:07 +0100319 void writeAll(Iterable<dynamic> objects, [ String separator = '' ]) {
Chris Bracken538ba522018-01-24 17:16:30 -0800320 bool addSeparator = false;
321 for (dynamic object in objects) {
322 if (addSeparator) {
323 write(separator);
324 }
325 write(object);
326 addSeparator = true;
327 }
328 }
329
330 @override
Alexandre Ardhuin5169ab52019-02-21 09:27:07 +0100331 void addError(dynamic error, [ StackTrace stackTrace ]) {
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200332 throw UnimplementedError();
Chris Bracken538ba522018-01-24 17:16:30 -0800333 }
334
335 @override
Alexandre Ardhuin2d3ff102018-10-05 07:54:56 +0200336 Future<void> get done => close();
Chris Bracken538ba522018-01-24 17:16:30 -0800337
338 @override
Alexandre Ardhuin8b0de382018-10-17 11:01:37 +0200339 Future<void> close() async { }
Chris Bracken538ba522018-01-24 17:16:30 -0800340
341 @override
Alexandre Ardhuin8b0de382018-10-17 11:01:37 +0200342 Future<void> flush() async { }
Chris Bracken538ba522018-01-24 17:16:30 -0800343}
344
345/// A Stdio that collects stdout and supports simulated stdin.
346class MockStdio extends Stdio {
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200347 final MemoryIOSink _stdout = MemoryIOSink();
Greg Spencer7caa6592018-09-19 15:22:43 -0700348 final MemoryIOSink _stderr = MemoryIOSink();
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200349 final StreamController<List<int>> _stdin = StreamController<List<int>>();
Chris Bracken538ba522018-01-24 17:16:30 -0800350
351 @override
352 IOSink get stdout => _stdout;
353
354 @override
Greg Spencer7caa6592018-09-19 15:22:43 -0700355 IOSink get stderr => _stderr;
356
357 @override
Chris Bracken538ba522018-01-24 17:16:30 -0800358 Stream<List<int>> get stdin => _stdin.stream;
359
360 void simulateStdin(String line) {
Jason Simmons466d1542018-03-12 11:06:32 -0700361 _stdin.add(utf8.encode('$line\n'));
Chris Bracken538ba522018-01-24 17:16:30 -0800362 }
363
Alexandre Ardhuinf62afdc2018-10-01 21:29:08 +0200364 List<String> get writtenToStdout => _stdout.writes.map<String>(_stdout.encoding.decode).toList();
365 List<String> get writtenToStderr => _stderr.writes.map<String>(_stderr.encoding.decode).toList();
Chris Bracken538ba522018-01-24 17:16:30 -0800366}
367
Devon Carew9ac2e442017-04-27 09:30:47 -0700368class MockPollingDeviceDiscovery extends PollingDeviceDiscovery {
Alexandre Ardhuin2ea1d812018-10-04 07:28:07 +0200369 MockPollingDeviceDiscovery() : super('mock');
370
Alexandre Ardhuin0783ec92017-09-01 22:18:51 +0200371 final List<Device> _devices = <Device>[];
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200372 final StreamController<Device> _onAddedController = StreamController<Device>.broadcast();
373 final StreamController<Device> _onRemovedController = StreamController<Device>.broadcast();
Devon Carew9ac2e442017-04-27 09:30:47 -0700374
Devon Carew9ac2e442017-04-27 09:30:47 -0700375 @override
Chris Bracken1d9f0092017-06-19 13:14:57 -0700376 Future<List<Device>> pollingGetDevices() async => _devices;
Devon Carew9ac2e442017-04-27 09:30:47 -0700377
378 @override
379 bool get supportsPlatform => true;
380
Todd Volkert6a4b08b2017-05-03 16:12:08 -0700381 @override
382 bool get canListAnything => true;
383
Devon Carew9ac2e442017-04-27 09:30:47 -0700384 void addDevice(MockAndroidDevice device) {
385 _devices.add(device);
386
387 _onAddedController.add(device);
388 }
389
390 @override
Chris Bracken1d9f0092017-06-19 13:14:57 -0700391 Future<List<Device>> get devices async => _devices;
Devon Carew9ac2e442017-04-27 09:30:47 -0700392
393 @override
394 Stream<Device> get onAdded => _onAddedController.stream;
395
396 @override
397 Stream<Device> get onRemoved => _onRemovedController.stream;
398}
399
Mikkel Nygaard Ravn22832d32018-08-30 16:18:44 +0200400class MockIosProject extends Mock implements IosProject {
401 @override
402 String get productBundleIdentifier => 'com.example.test';
403
404 @override
405 String get hostAppBundleName => 'Runner.app';
406}
407
Adam Barthbdd20662015-10-11 19:42:50 -0700408class MockAndroidDevice extends Mock implements AndroidDevice {
Hixie797e27e2016-03-14 13:31:43 -0700409 @override
Todd Volkert60c5ffc2017-04-25 17:23:00 -0700410 Future<TargetPlatform> get targetPlatform async => TargetPlatform.android_arm;
Hixie797e27e2016-03-14 13:31:43 -0700411
412 @override
Devon Carew37290d82016-02-24 10:06:59 -0800413 bool isSupported() => true;
Jonah Williams6b191842019-04-25 12:25:12 -0700414
415 @override
416 bool isSupportedForProject(FlutterProject flutterProject) => true;
Adam Barthbdd20662015-10-11 19:42:50 -0700417}
418
419class MockIOSDevice extends Mock implements IOSDevice {
Hixie797e27e2016-03-14 13:31:43 -0700420 @override
Todd Volkert60c5ffc2017-04-25 17:23:00 -0700421 Future<TargetPlatform> get targetPlatform async => TargetPlatform.ios;
Hixie797e27e2016-03-14 13:31:43 -0700422
423 @override
Devon Carew37290d82016-02-24 10:06:59 -0800424 bool isSupported() => true;
Jonah Williams6b191842019-04-25 12:25:12 -0700425
426 @override
427 bool isSupportedForProject(FlutterProject flutterProject) => true;
Adam Barthbdd20662015-10-11 19:42:50 -0700428}
429
430class MockIOSSimulator extends Mock implements IOSSimulator {
Hixie797e27e2016-03-14 13:31:43 -0700431 @override
Todd Volkert60c5ffc2017-04-25 17:23:00 -0700432 Future<TargetPlatform> get targetPlatform async => TargetPlatform.ios;
Hixie797e27e2016-03-14 13:31:43 -0700433
434 @override
Devon Carew37290d82016-02-24 10:06:59 -0800435 bool isSupported() => true;
Jonah Williams6b191842019-04-25 12:25:12 -0700436
437 @override
438 bool isSupportedForProject(FlutterProject flutterProject) => true;
Adam Barthbdd20662015-10-11 19:42:50 -0700439}
440
John McCutchan9cb70012016-03-04 15:01:26 -0800441class MockDeviceLogReader extends DeviceLogReader {
Hixie797e27e2016-03-14 13:31:43 -0700442 @override
John McCutchan9cb70012016-03-04 15:01:26 -0800443 String get name => 'MockLogReader';
444
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200445 final StreamController<String> _linesController = StreamController<String>.broadcast();
John McCutchan9cb70012016-03-04 15:01:26 -0800446
Hixie797e27e2016-03-14 13:31:43 -0700447 @override
Devon Carewb0dca792016-04-27 14:43:42 -0700448 Stream<String> get logLines => _linesController.stream;
John McCutchan9cb70012016-03-04 15:01:26 -0800449
Devon Carewb0dca792016-04-27 14:43:42 -0700450 void addLine(String line) => _linesController.add(line);
Dan Rubel672d04e2016-09-13 14:15:36 -0400451
452 void dispose() {
453 _linesController.close();
454 }
John McCutchan9cb70012016-03-04 15:01:26 -0800455}
456
Yegor Jbanov677e63b2016-02-25 15:58:09 -0800457void applyMocksToCommand(FlutterCommand command) {
Adam Barthbdd20662015-10-11 19:42:50 -0700458 command
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200459 ..applicationPackages = MockApplicationPackageStore();
Adam Barthbdd20662015-10-11 19:42:50 -0700460}
John McCutchan0de69162016-07-20 12:59:30 -0700461
Dan Rubel0295def2017-01-22 10:37:10 -0500462/// Common functionality for tracking mock interaction
463class BasicMock {
Alexandre Ardhuin329e52c2017-03-08 23:57:31 +0100464 final List<String> messages = <String>[];
John McCutchan0de69162016-07-20 12:59:30 -0700465
Dan Rubel0295def2017-01-22 10:37:10 -0500466 void expectMessages(List<String> expectedMessages) {
Alexandre Ardhuind927c932018-09-12 08:29:29 +0200467 final List<String> actualMessages = List<String>.from(messages);
Dan Rubel0295def2017-01-22 10:37:10 -0500468 messages.clear();
469 expect(actualMessages, unorderedEquals(expectedMessages));
470 }
471
John McCutchan0de69162016-07-20 12:59:30 -0700472 bool contains(String match) {
John McCutchanb6644732016-07-22 06:59:24 -0700473 print('Checking for `$match` in:');
474 print(messages);
Chris Bracken7a093162017-03-03 17:50:46 -0800475 final bool result = messages.contains(match);
John McCutchan0de69162016-07-20 12:59:30 -0700476 messages.clear();
477 return result;
478 }
Dan Rubel0295def2017-01-22 10:37:10 -0500479}
John McCutchan0de69162016-07-20 12:59:30 -0700480
Jonah Williams27876e02019-05-31 13:17:12 -0700481class MockDevFSOperations extends BasicMock implements DevFSOperations {
482 Map<Uri, DevFSContent> devicePathToContent = <Uri, DevFSContent>{};
483
484 @override
485 Future<Uri> create(String fsName) async {
486 messages.add('create $fsName');
487 return Uri.parse('file:///$fsName');
488 }
489
490 @override
491 Future<dynamic> destroy(String fsName) async {
492 messages.add('destroy $fsName');
493 }
494
495 @override
496 Future<dynamic> writeFile(String fsName, Uri deviceUri, DevFSContent content) async {
497 String message = 'writeFile $fsName $deviceUri';
498 if (content is DevFSFileContent) {
499 message += ' ${content.file.path}';
500 }
501 messages.add(message);
502 devicePathToContent[deviceUri] = content;
503 }
504}
Chris Bracken251e82d2018-08-31 13:31:56 -0700505
506class MockResidentCompiler extends BasicMock implements ResidentCompiler {
507 @override
Alexandre Ardhuina0d1f932019-03-09 09:03:11 +0100508 void accept() { }
Chris Bracken251e82d2018-08-31 13:31:56 -0700509
510 @override
Alexander Aprelev030dc3f2019-01-31 17:43:32 -0800511 Future<CompilerOutput> reject() async { return null; }
Chris Bracken251e82d2018-08-31 13:31:56 -0700512
513 @override
Alexandre Ardhuina0d1f932019-03-09 09:03:11 +0100514 void reset() { }
Chris Bracken251e82d2018-08-31 13:31:56 -0700515
516 @override
Alexandre Ardhuina0d1f932019-03-09 09:03:11 +0100517 Future<dynamic> shutdown() async { }
Chris Bracken251e82d2018-08-31 13:31:56 -0700518
519 @override
520 Future<CompilerOutput> compileExpression(
521 String expression,
522 List<String> definitions,
523 List<String> typeDefinitions,
524 String libraryUri,
525 String klass,
Alexandre Ardhuin387f8852019-03-01 08:17:55 +0100526 bool isStatic,
Chris Bracken251e82d2018-08-31 13:31:56 -0700527 ) async {
528 return null;
529 }
530 @override
Alexander Aprelev12c4e052019-03-20 21:58:15 -0700531 Future<CompilerOutput> recompile(String mainPath, List<Uri> invalidatedFiles, { String outputPath, String packagesFilePath }) async {
Chris Bracken251e82d2018-08-31 13:31:56 -0700532 fs.file(outputPath).createSync(recursive: true);
533 fs.file(outputPath).writeAsStringSync('compiled_kernel_output');
Ben Konyie8b98f92019-03-19 20:01:03 -0700534 return CompilerOutput(outputPath, 0, <Uri>[]);
Chris Bracken251e82d2018-08-31 13:31:56 -0700535 }
536}