mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[flutter_tools] remove even more mocks (#81618)
This commit is contained in:
parent
67aaa0e79b
commit
bfe16a8640
@ -4,21 +4,15 @@
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fake_async/fake_async.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/base/process.dart';
|
||||
import 'package:flutter_tools/src/base/terminal.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/fake_process_manager.dart';
|
||||
import '../../src/fakes.dart';
|
||||
import '../../src/mocks.dart' show MockProcessManager,
|
||||
flakyProcessFactory;
|
||||
|
||||
void main() {
|
||||
group('process exceptions', () {
|
||||
@ -64,66 +58,44 @@ void main() {
|
||||
});
|
||||
|
||||
group('output formatting', () {
|
||||
MockProcessManager mockProcessManager;
|
||||
FakeProcessManager processManager;
|
||||
ProcessUtils processUtils;
|
||||
BufferLogger mockLogger;
|
||||
BufferLogger logger;
|
||||
|
||||
setUp(() {
|
||||
mockProcessManager = MockProcessManager();
|
||||
mockLogger = BufferLogger(
|
||||
terminal: AnsiTerminal(
|
||||
stdio: FakeStdio(),
|
||||
platform: FakePlatform(stdoutSupportsAnsi: false),
|
||||
),
|
||||
outputPreferences: OutputPreferences(wrapText: true, wrapColumn: 40),
|
||||
);
|
||||
processManager = FakeProcessManager.empty();
|
||||
logger = BufferLogger.test();
|
||||
processUtils = ProcessUtils(
|
||||
processManager: mockProcessManager,
|
||||
logger: mockLogger,
|
||||
processManager: processManager,
|
||||
logger: logger,
|
||||
);
|
||||
});
|
||||
|
||||
FakeProcess Function(List<String>) processMetaFactory(List<String> stdout, {
|
||||
List<String> stderr = const <String>[],
|
||||
}) {
|
||||
final Stream<List<int>> stdoutStream = Stream<List<int>>.fromIterable(
|
||||
stdout.map<List<int>>((String s) => s.codeUnits,
|
||||
));
|
||||
final Stream<List<int>> stderrStream = Stream<List<int>>.fromIterable(
|
||||
stderr.map<List<int>>((String s) => s.codeUnits,
|
||||
));
|
||||
return (List<String> command) => FakeProcess(stdout: stdoutStream, stderr: stderrStream);
|
||||
}
|
||||
|
||||
testWithoutContext('Command output is not wrapped.', () async {
|
||||
final List<String> testString = <String>['0123456789' * 10];
|
||||
mockProcessManager.processFactory = processMetaFactory(testString, stderr: testString);
|
||||
processManager.addCommand(FakeCommand(
|
||||
command: const <String>['command'],
|
||||
stdout: testString.join(''),
|
||||
stderr: testString.join(''),
|
||||
));
|
||||
|
||||
await processUtils.stream(<String>['command']);
|
||||
expect(mockLogger.statusText, equals('${testString[0]}\n'));
|
||||
expect(mockLogger.errorText, equals('${testString[0]}\n'));
|
||||
|
||||
expect(logger.statusText, equals('${testString[0]}\n'));
|
||||
expect(logger.errorText, equals('${testString[0]}\n'));
|
||||
});
|
||||
});
|
||||
|
||||
group('run', () {
|
||||
const Duration delay = Duration(seconds: 2);
|
||||
MockProcessManager flakyProcessManager;
|
||||
FakeProcessManager fakeProcessManager;
|
||||
ProcessUtils processUtils;
|
||||
ProcessUtils flakyProcessUtils;
|
||||
|
||||
setUp(() {
|
||||
// MockProcessManager has an implementation of start() that returns the
|
||||
// result of processFactory.
|
||||
flakyProcessManager = MockProcessManager();
|
||||
fakeProcessManager = FakeProcessManager.empty();
|
||||
processUtils = ProcessUtils(
|
||||
processManager: fakeProcessManager,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
flakyProcessUtils = ProcessUtils(
|
||||
processManager: flakyProcessManager,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext(' succeeds on success', () async {
|
||||
@ -189,68 +161,6 @@ void main() {
|
||||
throwsA(isA<ProcessException>()),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext(' flaky process fails without retry', () async {
|
||||
flakyProcessManager.processFactory = flakyProcessFactory(
|
||||
flakes: 1,
|
||||
delay: delay,
|
||||
);
|
||||
|
||||
await FakeAsync().run((FakeAsync time) async {
|
||||
final Duration timeout = delay + const Duration(seconds: 1);
|
||||
final RunResult result = await flakyProcessUtils.run(
|
||||
<String>['dummy'],
|
||||
timeout: timeout,
|
||||
);
|
||||
time.elapse(timeout);
|
||||
expect(result.exitCode, -9);
|
||||
});
|
||||
}, skip: true); // TODO(jonahwilliams): clean up with https://github.com/flutter/flutter/issues/60675
|
||||
|
||||
testWithoutContext(' flaky process succeeds with retry', () async {
|
||||
flakyProcessManager.processFactory = flakyProcessFactory(
|
||||
flakes: 1,
|
||||
delay: delay,
|
||||
);
|
||||
await FakeAsync().run((FakeAsync time) async {
|
||||
final Duration timeout = delay - const Duration(milliseconds: 500);
|
||||
final RunResult result = await flakyProcessUtils.run(
|
||||
<String>['dummy'],
|
||||
timeout: timeout,
|
||||
timeoutRetries: 1,
|
||||
);
|
||||
time.elapse(timeout);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
}, skip: true); // TODO(jonahwilliams): clean up with https://github.com/flutter/flutter/issues/60675
|
||||
|
||||
testWithoutContext(' flaky process generates ProcessException on timeout', () async {
|
||||
final Completer<List<int>> flakyStderr = Completer<List<int>>();
|
||||
final Completer<List<int>> flakyStdout = Completer<List<int>>();
|
||||
flakyProcessManager.processFactory = flakyProcessFactory(
|
||||
flakes: 1,
|
||||
delay: delay,
|
||||
stderr: () => Stream<List<int>>.fromFuture(flakyStderr.future),
|
||||
stdout: () => Stream<List<int>>.fromFuture(flakyStdout.future),
|
||||
);
|
||||
when(flakyProcessManager.killPid(any)).thenAnswer((_) {
|
||||
// Don't let the stderr stream stop until the process is killed. This
|
||||
// ensures that runAsync() does not delay killing the process until
|
||||
// stdout and stderr are drained (which won't happen).
|
||||
flakyStderr.complete(<int>[]);
|
||||
flakyStdout.complete(<int>[]);
|
||||
return true;
|
||||
});
|
||||
await FakeAsync().run((FakeAsync time) async {
|
||||
final Duration timeout = delay - const Duration(milliseconds: 500);
|
||||
expect(() => flakyProcessUtils.run(
|
||||
<String>['dummy'],
|
||||
timeout: timeout,
|
||||
timeoutRetries: 0,
|
||||
), throwsA(isA<ProcessException>()));
|
||||
time.elapse(timeout);
|
||||
});
|
||||
}, skip: true); // TODO(jonahwilliams): clean up with https://github.com/flutter/flutter/issues/60675
|
||||
});
|
||||
|
||||
group('runSync', () {
|
||||
@ -404,50 +314,55 @@ void main() {
|
||||
});
|
||||
|
||||
group('exitsHappySync', () {
|
||||
MockProcessManager mockProcessManager;
|
||||
FakeProcessManager processManager;
|
||||
ProcessUtils processUtils;
|
||||
|
||||
setUp(() {
|
||||
mockProcessManager = MockProcessManager();
|
||||
processManager = FakeProcessManager.empty();
|
||||
processUtils = ProcessUtils(
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext(' succeeds on success', () async {
|
||||
when(mockProcessManager.runSync(<String>['whoohoo'])).thenReturn(
|
||||
ProcessResult(0, 0, '', '')
|
||||
);
|
||||
testWithoutContext('succeeds on success', () async {
|
||||
processManager.addCommand(const FakeCommand(
|
||||
command: <String>['whoohoo'],
|
||||
));
|
||||
|
||||
expect(processUtils.exitsHappySync(<String>['whoohoo']), isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext(' fails on failure', () async {
|
||||
when(mockProcessManager.runSync(<String>['boohoo'])).thenReturn(
|
||||
ProcessResult(0, 1, '', '')
|
||||
);
|
||||
testWithoutContext('fails on failure', () async {
|
||||
processManager.addCommand(const FakeCommand(
|
||||
command: <String>['boohoo'],
|
||||
exitCode: 1,
|
||||
));
|
||||
|
||||
expect(processUtils.exitsHappySync(<String>['boohoo']), isFalse);
|
||||
});
|
||||
|
||||
testWithoutContext('catches Exception and returns false', () {
|
||||
when(mockProcessManager.runSync(<String>['boohoo'])).thenThrow(
|
||||
const ProcessException('Process failed', <String>[]),
|
||||
);
|
||||
processManager.addCommand(const FakeCommand(
|
||||
command: <String>['boohoo'],
|
||||
exception: ProcessException('Process failed', <String>[]),
|
||||
));
|
||||
|
||||
expect(processUtils.exitsHappySync(<String>['boohoo']), isFalse);
|
||||
});
|
||||
|
||||
testWithoutContext('does not throw Exception and returns false if binary cannot run', () {
|
||||
mockProcessManager.canRunSucceeds = false;
|
||||
processManager.excludedExecutables.add('nonesuch');
|
||||
|
||||
expect(processUtils.exitsHappySync(<String>['nonesuch']), isFalse);
|
||||
verifyNever(
|
||||
mockProcessManager.runSync(any, environment: anyNamed('environment')),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('does not catch ArgumentError', () async {
|
||||
when(mockProcessManager.runSync(<String>['invalid'])).thenThrow(
|
||||
ArgumentError('Bad input'),
|
||||
);
|
||||
processManager.addCommand(FakeCommand(
|
||||
command: const <String>['invalid'],
|
||||
exception: ArgumentError('Bad input'),
|
||||
));
|
||||
|
||||
expect(
|
||||
() => processUtils.exitsHappySync(<String>['invalid']),
|
||||
throwsArgumentError,
|
||||
@ -456,50 +371,55 @@ void main() {
|
||||
});
|
||||
|
||||
group('exitsHappy', () {
|
||||
MockProcessManager mockProcessManager;
|
||||
FakeProcessManager processManager;
|
||||
ProcessUtils processUtils;
|
||||
|
||||
setUp(() {
|
||||
mockProcessManager = MockProcessManager();
|
||||
processManager = FakeProcessManager.empty();
|
||||
processUtils = ProcessUtils(
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('succeeds on success', () async {
|
||||
when(mockProcessManager.run(<String>['whoohoo'])).thenAnswer((_) {
|
||||
return Future<ProcessResult>.value(ProcessResult(0, 0, '', ''));
|
||||
});
|
||||
processManager.addCommand(const FakeCommand(
|
||||
command: <String>['whoohoo']
|
||||
));
|
||||
|
||||
expect(await processUtils.exitsHappy(<String>['whoohoo']), isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('fails on failure', () async {
|
||||
when(mockProcessManager.run(<String>['boohoo'])).thenAnswer((_) {
|
||||
return Future<ProcessResult>.value(ProcessResult(0, 1, '', ''));
|
||||
});
|
||||
processManager.addCommand(const FakeCommand(
|
||||
command: <String>['boohoo'],
|
||||
exitCode: 1,
|
||||
));
|
||||
|
||||
expect(await processUtils.exitsHappy(<String>['boohoo']), isFalse);
|
||||
});
|
||||
|
||||
testWithoutContext('catches Exception and returns false', () async {
|
||||
when(mockProcessManager.run(<String>['boohoo'])).thenThrow(
|
||||
const ProcessException('Process failed', <String>[]),
|
||||
);
|
||||
processManager.addCommand(const FakeCommand(
|
||||
command: <String>['boohoo'],
|
||||
exception: ProcessException('Process failed', <String>[])
|
||||
));
|
||||
|
||||
expect(await processUtils.exitsHappy(<String>['boohoo']), isFalse);
|
||||
});
|
||||
|
||||
testWithoutContext('does not throw Exception and returns false if binary cannot run', () async {
|
||||
mockProcessManager.canRunSucceeds = false;
|
||||
processManager.excludedExecutables.add('nonesuch');
|
||||
|
||||
expect(await processUtils.exitsHappy(<String>['nonesuch']), isFalse);
|
||||
verifyNever(
|
||||
mockProcessManager.runSync(any, environment: anyNamed('environment')),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('does not catch ArgumentError', () async {
|
||||
when(mockProcessManager.run(<String>['invalid'])).thenThrow(
|
||||
ArgumentError('Bad input'),
|
||||
);
|
||||
processManager.addCommand(FakeCommand(
|
||||
command: const <String>['invalid'],
|
||||
exception: ArgumentError('Bad input')
|
||||
));
|
||||
|
||||
expect(
|
||||
() async => processUtils.exitsHappy(<String>['invalid']),
|
||||
throwsArgumentError,
|
||||
|
@ -4,21 +4,16 @@
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io' hide Directory, File;
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/base/terminal.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/build_system/build_system.dart';
|
||||
import 'package:flutter_tools/src/build_system/targets/icon_tree_shaker.dart';
|
||||
import 'package:flutter_tools/src/devfs.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../../../src/common.dart';
|
||||
import '../../../src/fake_process_manager.dart';
|
||||
@ -34,8 +29,7 @@ const String relativePath = 'fonts/MaterialIcons-Regular.otf';
|
||||
void main() {
|
||||
BufferLogger logger;
|
||||
MemoryFileSystem fileSystem;
|
||||
MockProcessManager mockProcessManager;
|
||||
MockProcess fontSubsetProcess;
|
||||
FakeProcessManager processManager;
|
||||
Artifacts artifacts;
|
||||
DevFSStringContent fontManifestContent;
|
||||
|
||||
@ -59,9 +53,12 @@ void main() {
|
||||
String stdout = '',
|
||||
String stderr = '',
|
||||
}) {
|
||||
when(mockProcessManager.run(_getConstFinderArgs(appDillPath))).thenAnswer((_) async {
|
||||
return ProcessResult(0, exitCode, stdout, stderr);
|
||||
});
|
||||
processManager.addCommand(FakeCommand(
|
||||
command: _getConstFinderArgs(appDillPath),
|
||||
exitCode: exitCode,
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
));
|
||||
}
|
||||
|
||||
void _resetFontSubsetInvocation({
|
||||
@ -72,30 +69,21 @@ void main() {
|
||||
}) {
|
||||
assert(stdinSink != null);
|
||||
stdinSink.clear();
|
||||
when(fontSubsetProcess.exitCode).thenAnswer((_) async => exitCode);
|
||||
when(fontSubsetProcess.stdout).thenAnswer((_) => Stream<List<int>>.fromIterable(<List<int>>[utf8.encode(stdout)]));
|
||||
when(fontSubsetProcess.stderr).thenAnswer((_) => Stream<List<int>>.fromIterable(<List<int>>[utf8.encode(stderr)]));
|
||||
when(fontSubsetProcess.stdin).thenReturn(stdinSink);
|
||||
when(mockProcessManager.start(fontSubsetArgs)).thenAnswer((_) async {
|
||||
return fontSubsetProcess;
|
||||
});
|
||||
processManager.addCommand(FakeCommand(
|
||||
command: fontSubsetArgs,
|
||||
exitCode: exitCode,
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
stdin: stdinSink,
|
||||
));
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
processManager = FakeProcessManager.empty();
|
||||
fontManifestContent = DevFSStringContent(validFontManifestJson);
|
||||
|
||||
mockProcessManager = MockProcessManager();
|
||||
fontSubsetProcess = MockProcess();
|
||||
artifacts = Artifacts.test();
|
||||
fileSystem = MemoryFileSystem.test();
|
||||
logger = BufferLogger(
|
||||
terminal: AnsiTerminal(
|
||||
stdio: FakeStdio(),
|
||||
platform: kNoAnsiPlatform,
|
||||
),
|
||||
outputPreferences: OutputPreferences.test(showColor: false),
|
||||
);
|
||||
|
||||
logger = BufferLogger.test();
|
||||
dartPath = artifacts.getHostArtifact(HostArtifact.engineDartBinary).path;
|
||||
constFinderPath = artifacts.getArtifactPath(Artifact.constFinder);
|
||||
fontSubsetPath = artifacts.getArtifactPath(Artifact.fontSubset);
|
||||
@ -135,7 +123,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -153,9 +141,7 @@ void main() {
|
||||
relativePath: relativePath,
|
||||
);
|
||||
expect(subsets, false);
|
||||
|
||||
verifyNever(mockProcessManager.run(any));
|
||||
verifyNever(mockProcessManager.start(any));
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('Does not get enabled without font manifest', () {
|
||||
@ -168,7 +154,7 @@ void main() {
|
||||
environment,
|
||||
null,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -178,8 +164,7 @@ void main() {
|
||||
isEmpty,
|
||||
);
|
||||
expect(iconTreeShaker.enabled, false);
|
||||
verifyNever(mockProcessManager.run(any));
|
||||
verifyNever(mockProcessManager.start(any));
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('Gets enabled', () {
|
||||
@ -192,7 +177,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -202,8 +187,7 @@ void main() {
|
||||
isEmpty,
|
||||
);
|
||||
expect(iconTreeShaker.enabled, true);
|
||||
verifyNever(mockProcessManager.run(any));
|
||||
verifyNever(mockProcessManager.start(any));
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
test('No app.dill throws exception', () async {
|
||||
@ -216,7 +200,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -229,6 +213,7 @@ void main() {
|
||||
),
|
||||
throwsA(isA<IconTreeShakerException>()),
|
||||
);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('Can subset a font', () async {
|
||||
@ -243,7 +228,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -268,9 +253,7 @@ void main() {
|
||||
);
|
||||
expect(subsetted, true);
|
||||
expect(stdinSink.getAndClear(), '59470\n');
|
||||
|
||||
verify(mockProcessManager.run(_getConstFinderArgs(appDill.path))).called(1);
|
||||
verify(mockProcessManager.start(fontSubsetArgs)).called(2);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('Does not subset a non-supported font', () async {
|
||||
@ -285,7 +268,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -303,9 +286,6 @@ void main() {
|
||||
relativePath: relativePath,
|
||||
);
|
||||
expect(subsetted, false);
|
||||
|
||||
verifyNever(mockProcessManager.run(_getConstFinderArgs(appDill.path)));
|
||||
verifyNever(mockProcessManager.start(fontSubsetArgs));
|
||||
});
|
||||
|
||||
testWithoutContext('Does not subset an invalid ttf font', () async {
|
||||
@ -320,7 +300,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -338,8 +318,6 @@ void main() {
|
||||
);
|
||||
|
||||
expect(subsetted, false);
|
||||
verifyNever(mockProcessManager.run(_getConstFinderArgs(appDill.path)));
|
||||
verifyNever(mockProcessManager.start(fontSubsetArgs));
|
||||
});
|
||||
|
||||
testWithoutContext('Non-constant instances', () async {
|
||||
@ -354,7 +332,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -362,7 +340,7 @@ void main() {
|
||||
_addConstFinderInvocation(appDill.path, stdout: constFinderResultWithInvalid);
|
||||
|
||||
await expectLater(
|
||||
() async => iconTreeShaker.subsetFont(
|
||||
() => iconTreeShaker.subsetFont(
|
||||
input: fileSystem.file(inputPath),
|
||||
outputPath: outputPath,
|
||||
relativePath: relativePath,
|
||||
@ -373,9 +351,7 @@ void main() {
|
||||
' again with --no-tree-shake-icons.',
|
||||
),
|
||||
);
|
||||
|
||||
verify(mockProcessManager.run(_getConstFinderArgs(appDill.path))).called(1);
|
||||
verifyNever(mockProcessManager.start(fontSubsetArgs));
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('Non-zero font-subset exit code', () async {
|
||||
@ -391,7 +367,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -401,16 +377,14 @@ void main() {
|
||||
_resetFontSubsetInvocation(exitCode: -1, stdinSink: stdinSink);
|
||||
|
||||
await expectLater(
|
||||
() async => iconTreeShaker.subsetFont(
|
||||
() => iconTreeShaker.subsetFont(
|
||||
input: fileSystem.file(inputPath),
|
||||
outputPath: outputPath,
|
||||
relativePath: relativePath,
|
||||
),
|
||||
throwsA(isA<IconTreeShakerException>()),
|
||||
);
|
||||
|
||||
verify(mockProcessManager.run(_getConstFinderArgs(appDill.path))).called(1);
|
||||
verify(mockProcessManager.start(fontSubsetArgs)).called(1);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('font-subset throws on write to sdtin', () async {
|
||||
@ -425,7 +399,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -435,16 +409,14 @@ void main() {
|
||||
_resetFontSubsetInvocation(exitCode: -1, stdinSink: stdinSink);
|
||||
|
||||
await expectLater(
|
||||
() async => iconTreeShaker.subsetFont(
|
||||
() => iconTreeShaker.subsetFont(
|
||||
input: fileSystem.file(inputPath),
|
||||
outputPath: outputPath,
|
||||
relativePath: relativePath,
|
||||
),
|
||||
throwsA(isA<IconTreeShakerException>()),
|
||||
);
|
||||
|
||||
verify(mockProcessManager.run(_getConstFinderArgs(appDill.path))).called(1);
|
||||
verify(mockProcessManager.start(fontSubsetArgs)).called(1);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('Invalid font manifest', () async {
|
||||
@ -461,7 +433,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -469,16 +441,14 @@ void main() {
|
||||
_addConstFinderInvocation(appDill.path, stdout: validConstFinderResult);
|
||||
|
||||
await expectLater(
|
||||
() async => iconTreeShaker.subsetFont(
|
||||
() => iconTreeShaker.subsetFont(
|
||||
input: fileSystem.file(inputPath),
|
||||
outputPath: outputPath,
|
||||
relativePath: relativePath,
|
||||
),
|
||||
throwsA(isA<IconTreeShakerException>()),
|
||||
);
|
||||
|
||||
verify(mockProcessManager.run(_getConstFinderArgs(appDill.path))).called(1);
|
||||
verifyNever(mockProcessManager.start(fontSubsetArgs));
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
|
||||
testWithoutContext('ConstFinder non-zero exit', () async {
|
||||
@ -495,7 +465,7 @@ void main() {
|
||||
environment,
|
||||
fontManifestContent,
|
||||
logger: logger,
|
||||
processManager: mockProcessManager,
|
||||
processManager: processManager,
|
||||
fileSystem: fileSystem,
|
||||
artifacts: artifacts,
|
||||
);
|
||||
@ -510,9 +480,7 @@ void main() {
|
||||
),
|
||||
throwsA(isA<IconTreeShakerException>()),
|
||||
);
|
||||
|
||||
verify(mockProcessManager.run(_getConstFinderArgs(appDill.path))).called(1);
|
||||
verifyNever(mockProcessManager.start(fontSubsetArgs));
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
});
|
||||
}
|
||||
|
||||
@ -589,6 +557,3 @@ const String invalidFontManifestJson = '''
|
||||
]
|
||||
}
|
||||
''';
|
||||
|
||||
class MockProcessManager extends Mock implements ProcessManager {}
|
||||
class MockProcess extends Mock implements Process {}
|
||||
|
@ -20,7 +20,7 @@ import 'package:flutter_tools/src/ios/devices.dart';
|
||||
import 'package:flutter_tools/src/ios/ios_deploy.dart';
|
||||
import 'package:flutter_tools/src/ios/iproxy.dart';
|
||||
import 'package:flutter_tools/src/ios/mac.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:test/fake.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/fake_devices.dart';
|
||||
@ -86,12 +86,10 @@ stdout: '(lldb) run\nsuccess',
|
||||
);
|
||||
|
||||
void main() {
|
||||
// TODO(jonahwilliams): This test doesn't really belong here but
|
||||
// I don't have a better place for it for now.
|
||||
testWithoutContext('disposing device disposes the portForwarder and logReader', () async {
|
||||
final IOSDevice device = setUpIOSDevice();
|
||||
final DevicePortForwarder devicePortForwarder = MockDevicePortForwarder();
|
||||
final DeviceLogReader deviceLogReader = MockDeviceLogReader();
|
||||
final FakeDevicePortForwarder devicePortForwarder = FakeDevicePortForwarder();
|
||||
final FakeDeviceLogReader deviceLogReader = FakeDeviceLogReader();
|
||||
final IOSApp iosApp = PrebuiltIOSApp(
|
||||
projectBundleId: 'app',
|
||||
bundleName: 'Runner',
|
||||
@ -101,8 +99,8 @@ void main() {
|
||||
device.setLogReader(iosApp, deviceLogReader);
|
||||
await device.dispose();
|
||||
|
||||
verify(deviceLogReader.dispose()).called(1);
|
||||
verify(devicePortForwarder.dispose()).called(1);
|
||||
expect(deviceLogReader.disposed, true);
|
||||
expect(devicePortForwarder.disposed, true);
|
||||
});
|
||||
|
||||
testWithoutContext('IOSDevice.startApp attaches in debug mode via log reading on iOS 13+', () async {
|
||||
@ -384,5 +382,11 @@ IOSDevice setUpIOSDevice({
|
||||
);
|
||||
}
|
||||
|
||||
class MockDevicePortForwarder extends Mock implements DevicePortForwarder {}
|
||||
class MockDeviceLogReader extends Mock implements DeviceLogReader {}
|
||||
class FakeDevicePortForwarder extends Fake implements DevicePortForwarder {
|
||||
bool disposed = false;
|
||||
|
||||
@override
|
||||
Future<void> dispose() async {
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
@ -16,55 +16,17 @@ import 'package:flutter_tools/src/ios/xcode_build_settings.dart';
|
||||
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/mocks.dart' as mocks;
|
||||
|
||||
const String xcodebuild = '/usr/bin/xcodebuild';
|
||||
|
||||
void main() {
|
||||
group('MockProcessManager', () {
|
||||
mocks.MockProcessManager processManager;
|
||||
XcodeProjectInterpreter xcodeProjectInterpreter;
|
||||
FakePlatform platform;
|
||||
BufferLogger logger;
|
||||
|
||||
setUp(() {
|
||||
processManager = mocks.MockProcessManager();
|
||||
platform = FakePlatform(operatingSystem: 'macos');
|
||||
final FileSystem fileSystem = MemoryFileSystem.test();
|
||||
fileSystem.file(xcodebuild).createSync(recursive: true);
|
||||
logger = BufferLogger.test();
|
||||
xcodeProjectInterpreter = XcodeProjectInterpreter(
|
||||
logger: logger,
|
||||
fileSystem: fileSystem,
|
||||
platform: platform,
|
||||
processManager: processManager,
|
||||
usage: null,
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('xcodebuild build settings flakes', () async {
|
||||
const Duration delay = Duration(seconds: 1);
|
||||
processManager.processFactory = mocks.flakyProcessFactory(
|
||||
flakes: 1,
|
||||
delay: delay + const Duration(seconds: 1),
|
||||
);
|
||||
platform.environment = const <String, String>{};
|
||||
|
||||
when(processManager.runSync(<String>['which', 'sysctl']))
|
||||
.thenReturn(ProcessResult(0, 0, '', ''));
|
||||
when(processManager.runSync(<String>['sysctl', 'hw.optional.arm64']))
|
||||
.thenReturn(ProcessResult(0, 1, '', ''));
|
||||
|
||||
expect(await xcodeProjectInterpreter.getBuildSettings('', buildContext: const XcodeProjectBuildContext(scheme: 'Runner'), timeout: delay),
|
||||
const <String, String>{});
|
||||
// build settings times out and is killed once, then succeeds.
|
||||
verify(processManager.killPid(any)).called(1);
|
||||
// The verbose logs should tell us something timed out.
|
||||
expect(logger.traceText, contains('timed out'));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -7,66 +7,60 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/application_package.dart';
|
||||
import 'package:flutter_tools/src/base/common.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/time.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/build_system/build_system.dart';
|
||||
import 'package:flutter_tools/src/devfs.dart';
|
||||
import 'package:flutter_tools/src/device.dart';
|
||||
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
|
||||
import 'package:flutter_tools/src/isolated/devfs_web.dart';
|
||||
import 'package:flutter_tools/src/isolated/resident_web_runner.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||
import 'package:flutter_tools/src/resident_runner.dart';
|
||||
import 'package:flutter_tools/src/web/chrome.dart';
|
||||
import 'package:flutter_tools/src/web/web_device.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
|
||||
import 'package:flutter_tools/src/vmservice.dart';
|
||||
import 'package:test/fake.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/fakes.dart';
|
||||
import '../src/test_build_system.dart';
|
||||
|
||||
void main() {
|
||||
ResidentWebRunner residentWebRunner;
|
||||
MockFlutterDevice mockFlutterDevice;
|
||||
MockWebDevFS mockWebDevFS;
|
||||
FakeFlutterDevice mockFlutterDevice;
|
||||
FakeWebDevFS mockWebDevFS;
|
||||
FileSystem fileSystem;
|
||||
|
||||
setUp(() {
|
||||
mockWebDevFS = MockWebDevFS();
|
||||
final MockWebDevice mockWebDevice = MockWebDevice();
|
||||
mockFlutterDevice = MockFlutterDevice();
|
||||
when(mockFlutterDevice.device).thenReturn(mockWebDevice);
|
||||
when(mockFlutterDevice.devFS).thenReturn(mockWebDevFS);
|
||||
when(mockWebDevFS.sources).thenReturn(<Uri>[]);
|
||||
fileSystem = MemoryFileSystem.test();
|
||||
mockWebDevFS = FakeWebDevFS();
|
||||
final FakeWebDevice mockWebDevice = FakeWebDevice();
|
||||
mockFlutterDevice = FakeFlutterDevice(mockWebDevice);
|
||||
mockFlutterDevice._devFS = mockWebDevFS;
|
||||
|
||||
fileSystem.file('.packages').writeAsStringSync('\n');
|
||||
fileSystem.file('pubspec.yaml').createSync();
|
||||
fileSystem.file(fileSystem.path.join('lib', 'main.dart')).createSync(recursive: true);
|
||||
fileSystem.file(fileSystem.path.join('web', 'index.html')).createSync(recursive: true);
|
||||
});
|
||||
|
||||
void _setupMocks() {
|
||||
globals.fs.file('.packages').writeAsStringSync('\n');
|
||||
globals.fs.file('pubspec.yaml').createSync();
|
||||
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
|
||||
globals.fs.file(globals.fs.path.join('web', 'index.html')).createSync(recursive: true);
|
||||
final FlutterProject project = FlutterProject.fromDirectoryTest(globals.fs.currentDirectory);
|
||||
residentWebRunner = ResidentWebRunner(
|
||||
testUsingContext('Can successfully run and connect without vmservice', () async {
|
||||
final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
|
||||
final ResidentWebRunner residentWebRunner = ResidentWebRunner(
|
||||
mockFlutterDevice,
|
||||
flutterProject: project,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
ipv6: true,
|
||||
stayResident: true,
|
||||
urlTunneller: null,
|
||||
fileSystem: globals.fs,
|
||||
logger: globals.logger,
|
||||
systemClock: globals.systemClock,
|
||||
usage: globals.flutterUsage,
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
|
||||
usage: TestUsage(),
|
||||
);
|
||||
}
|
||||
|
||||
testUsingContext('Can successfully run and connect without vmservice', () async {
|
||||
_setupMocks();
|
||||
final FakeStatusLogger fakeStatusLogger = globals.logger as FakeStatusLogger;
|
||||
final MockStatus mockStatus = MockStatus();
|
||||
fakeStatusLogger.status = mockStatus;
|
||||
final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
|
||||
unawaited(residentWebRunner.run(
|
||||
connectionInfoCompleter: connectionInfoCompleter,
|
||||
@ -74,40 +68,74 @@ void main() {
|
||||
final DebugConnectionInfo debugConnectionInfo = await connectionInfoCompleter.future;
|
||||
|
||||
expect(debugConnectionInfo.wsUri, null);
|
||||
verify(mockStatus.stop()).called(1);
|
||||
}, overrides: <Type, Generator>{
|
||||
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
|
||||
Logger: () => FakeStatusLogger(BufferLogger.test()),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/60613
|
||||
testUsingContext('ResidentWebRunner calls appFailedToStart if initial compilation fails', () async {
|
||||
_setupMocks();
|
||||
final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
|
||||
final ResidentWebRunner residentWebRunner = ResidentWebRunner(
|
||||
mockFlutterDevice,
|
||||
flutterProject: project,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
ipv6: true,
|
||||
stayResident: true,
|
||||
urlTunneller: null,
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
|
||||
usage: TestUsage(),
|
||||
);
|
||||
|
||||
expect(() async => residentWebRunner.run(), throwsToolExit());
|
||||
expect(() => residentWebRunner.run(), throwsToolExit());
|
||||
expect(await residentWebRunner.waitForAppToFinish(), 1);
|
||||
}, overrides: <Type, Generator>{
|
||||
BuildSystem: () => TestBuildSystem.all(BuildResult(success: false)),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/60613
|
||||
testUsingContext('ResidentWebRunner calls appFailedToStart if error is thrown during startup', () async {
|
||||
_setupMocks();
|
||||
final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
|
||||
final ResidentWebRunner residentWebRunner = ResidentWebRunner(
|
||||
mockFlutterDevice,
|
||||
flutterProject: project,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
ipv6: true,
|
||||
stayResident: true,
|
||||
urlTunneller: null,
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
|
||||
usage: TestUsage(),
|
||||
);
|
||||
|
||||
expect(() async => residentWebRunner.run(), throwsA(isA<Exception>()));
|
||||
expect(await residentWebRunner.waitForAppToFinish(), 1);
|
||||
}, overrides: <Type, Generator>{
|
||||
BuildSystem: () => TestBuildSystem.error(Exception('foo')),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('Can full restart after attaching', () async {
|
||||
_setupMocks();
|
||||
final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
|
||||
final ResidentWebRunner residentWebRunner = ResidentWebRunner(
|
||||
mockFlutterDevice,
|
||||
flutterProject: project,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
ipv6: true,
|
||||
stayResident: true,
|
||||
urlTunneller: null,
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
|
||||
usage: TestUsage(),
|
||||
);
|
||||
final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
|
||||
unawaited(residentWebRunner.run(
|
||||
connectionInfoCompleter: connectionInfoCompleter,
|
||||
@ -118,12 +146,24 @@ void main() {
|
||||
expect(result.code, 0);
|
||||
}, overrides: <Type, Generator>{
|
||||
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('Fails on compilation errors in hot restart', () async {
|
||||
_setupMocks();
|
||||
final FlutterProject project = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
|
||||
final ResidentWebRunner residentWebRunner = ResidentWebRunner(
|
||||
mockFlutterDevice,
|
||||
flutterProject: project,
|
||||
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
||||
ipv6: true,
|
||||
stayResident: true,
|
||||
urlTunneller: null,
|
||||
fileSystem: fileSystem,
|
||||
logger: BufferLogger.test(),
|
||||
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
|
||||
usage: TestUsage(),
|
||||
);
|
||||
final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
|
||||
unawaited(residentWebRunner.run(
|
||||
connectionInfoCompleter: connectionInfoCompleter,
|
||||
@ -138,55 +178,63 @@ void main() {
|
||||
BuildResult(success: true),
|
||||
BuildResult(success: false),
|
||||
]),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('Correctly performs a full refresh on attached chrome device.', () async {
|
||||
_setupMocks();
|
||||
final MockChromeDevice chromeDevice = MockChromeDevice();
|
||||
final MockChrome chrome = MockChrome();
|
||||
final MockChromeConnection mockChromeConnection = MockChromeConnection();
|
||||
final MockChromeTab mockChromeTab = MockChromeTab();
|
||||
final MockWipConnection mockWipConnection = MockWipConnection();
|
||||
final MockChromiumLauncher chromiumLauncher = MockChromiumLauncher();
|
||||
when(mockChromeConnection.getTab(any)).thenAnswer((Invocation invocation) async {
|
||||
return mockChromeTab;
|
||||
});
|
||||
when(mockChromeTab.connect()).thenAnswer((Invocation invocation) async {
|
||||
return mockWipConnection;
|
||||
});
|
||||
when(chromiumLauncher.connectedInstance).thenAnswer((Invocation invocation) async {
|
||||
return chrome;
|
||||
});
|
||||
when(chrome.chromeConnection).thenReturn(mockChromeConnection);
|
||||
when(chromeDevice.chromeLauncher).thenReturn(chromiumLauncher);
|
||||
when(mockFlutterDevice.device).thenReturn(chromeDevice);
|
||||
final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
|
||||
unawaited(residentWebRunner.run(
|
||||
connectionInfoCompleter: connectionInfoCompleter,
|
||||
));
|
||||
await connectionInfoCompleter.future;
|
||||
final OperationResult result = await residentWebRunner.restart(fullRestart: true);
|
||||
|
||||
expect(result.code, 0);
|
||||
verify(mockWipConnection.sendCommand('Page.reload', <String, Object>{
|
||||
'ignoreCache': true,
|
||||
})).called(1);
|
||||
}, overrides: <Type, Generator>{
|
||||
BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
}
|
||||
|
||||
class MockWebDevFS extends Mock implements WebDevFS {}
|
||||
class MockWebDevice extends Mock implements Device {}
|
||||
class MockStatus extends Mock implements Status {}
|
||||
class MockFlutterDevice extends Mock implements FlutterDevice {}
|
||||
class MockChromeDevice extends Mock implements ChromiumDevice {}
|
||||
class MockChrome extends Mock implements Chromium {}
|
||||
class MockChromeConnection extends Mock implements ChromeConnection {}
|
||||
class MockChromeTab extends Mock implements ChromeTab {}
|
||||
class MockWipConnection extends Mock implements WipConnection {}
|
||||
class MockChromiumLauncher extends Mock implements ChromiumLauncher {}
|
||||
class FakeWebDevFS extends Fake implements WebDevFS {
|
||||
@override
|
||||
List<Uri> get sources => <Uri>[];
|
||||
|
||||
@override
|
||||
Future<Uri> create() async {
|
||||
return Uri.base;
|
||||
}
|
||||
}
|
||||
|
||||
class FakeWebDevice extends Fake implements Device {
|
||||
@override
|
||||
String get name => 'web';
|
||||
|
||||
@override
|
||||
Future<bool> stopApp(
|
||||
covariant ApplicationPackage app, {
|
||||
String userIdentifier,
|
||||
}) async {
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LaunchResult> startApp(
|
||||
covariant ApplicationPackage package, {
|
||||
String mainPath,
|
||||
String route,
|
||||
DebuggingOptions debuggingOptions,
|
||||
Map<String, dynamic> platformArgs,
|
||||
bool prebuiltApplication = false,
|
||||
bool ipv6 = false,
|
||||
String userIdentifier,
|
||||
}) async {
|
||||
return LaunchResult.succeeded();
|
||||
}
|
||||
}
|
||||
|
||||
class FakeFlutterDevice extends Fake implements FlutterDevice {
|
||||
FakeFlutterDevice(this.device);
|
||||
|
||||
@override
|
||||
final FakeWebDevice device;
|
||||
|
||||
|
||||
DevFS _devFS;
|
||||
|
||||
@override
|
||||
DevFS get devFS => _devFS;
|
||||
|
||||
@override
|
||||
set devFS(DevFS value) { }
|
||||
|
||||
@override
|
||||
FlutterVmService vmService;
|
||||
}
|
||||
|
@ -184,6 +184,8 @@ class FakeDeviceLogReader extends DeviceLogReader {
|
||||
|
||||
StreamController<String> _cachedLinesController;
|
||||
|
||||
bool disposed = false;
|
||||
|
||||
final List<String> _lineQueue = <String>[];
|
||||
StreamController<String> get _linesController {
|
||||
_cachedLinesController ??= StreamController<String>
|
||||
@ -209,5 +211,6 @@ class FakeDeviceLogReader extends DeviceLogReader {
|
||||
Future<void> dispose() async {
|
||||
_lineQueue.clear();
|
||||
await _linesController.close();
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
@ -1,88 +0,0 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:process/process.dart';
|
||||
|
||||
import 'fakes.dart';
|
||||
|
||||
/// A strategy for creating Process objects from a list of commands.
|
||||
typedef _ProcessFactory = Process Function(List<String> command);
|
||||
|
||||
/// A ProcessManager that starts Processes by delegating to a ProcessFactory.
|
||||
class MockProcessManager extends Mock implements ProcessManager {
|
||||
_ProcessFactory processFactory = _defaulProcessFactory;
|
||||
bool canRunSucceeds = true;
|
||||
bool runSucceeds = true;
|
||||
List<String> commands;
|
||||
|
||||
static Process _defaulProcessFactory(List<String> commands) => FakeProcess();
|
||||
|
||||
@override
|
||||
bool canRun(dynamic command, { String workingDirectory }) => canRunSucceeds;
|
||||
|
||||
@override
|
||||
Future<Process> start(
|
||||
List<dynamic> command, {
|
||||
String workingDirectory,
|
||||
Map<String, String> environment,
|
||||
bool includeParentEnvironment = true,
|
||||
bool runInShell = false,
|
||||
ProcessStartMode mode = ProcessStartMode.normal,
|
||||
}) {
|
||||
final List<String> commands = command.cast<String>();
|
||||
if (!runSucceeds) {
|
||||
final String executable = commands[0];
|
||||
final List<String> arguments = commands.length > 1 ? commands.sublist(1) : <String>[];
|
||||
throw ProcessException(executable, arguments);
|
||||
}
|
||||
|
||||
this.commands = commands;
|
||||
return Future<Process>.value(processFactory(commands));
|
||||
}
|
||||
}
|
||||
|
||||
/// A function that generates a process factory that gives processes that fail
|
||||
/// a given number of times before succeeding. The returned processes will
|
||||
/// fail after a delay if one is supplied.
|
||||
_ProcessFactory flakyProcessFactory({
|
||||
int flakes,
|
||||
bool Function(List<String> command) filter,
|
||||
Duration delay,
|
||||
Stream<List<int>> Function() stdout,
|
||||
Stream<List<int>> Function() stderr,
|
||||
}) {
|
||||
int flakesLeft = flakes;
|
||||
stdout ??= () => const Stream<List<int>>.empty();
|
||||
stderr ??= () => const Stream<List<int>>.empty();
|
||||
return (List<String> command) {
|
||||
if (filter != null && !filter(command)) {
|
||||
return FakeProcess();
|
||||
}
|
||||
if (flakesLeft == 0) {
|
||||
return FakeProcess(
|
||||
exitCode: Future<int>.value(0),
|
||||
stdout: stdout(),
|
||||
stderr: stderr(),
|
||||
);
|
||||
}
|
||||
flakesLeft = flakesLeft - 1;
|
||||
Future<int> exitFuture;
|
||||
if (delay == null) {
|
||||
exitFuture = Future<int>.value(-9);
|
||||
} else {
|
||||
exitFuture = Future<int>.delayed(delay, () => Future<int>.value(-9));
|
||||
}
|
||||
return FakeProcess(
|
||||
exitCode: exitFuture,
|
||||
stdout: stdout(),
|
||||
stderr: stderr(),
|
||||
);
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user