// 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. import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/commands/build.dart'; import 'package:flutter_tools/src/runner/flutter_command.dart'; import '../../src/common.dart'; import '../../src/context.dart'; import '../../src/fakes.dart'; import '../../src/test_build_system.dart'; import '../../src/test_flutter_command_runner.dart'; void main() { testUsingContext('obfuscate requires split-debug-info', () { final FakeBuildInfoCommand command = FakeBuildInfoCommand(); final CommandRunner<void> commandRunner = createTestCommandRunner(command); expect(() => commandRunner.run(<String>[ 'fake', '--obfuscate', ]), throwsToolExit(message: '"--${FlutterOptions.kDartObfuscationOption}" can only be used in ' 'combination with "--${FlutterOptions.kSplitDebugInfoOption}"')); }); group('Fatal Logs', () { late FakeBuildCommand command; late MemoryFileSystem fs; setUp(() { fs = MemoryFileSystem.test(); fs.file('/package/pubspec.yaml').createSync(recursive: true); fs.currentDirectory = '/package'; Cache.disableLocking(); }); testUsingContext("doesn't fail if --fatal-warnings specified and no warnings occur", () async { command = FakeBuildCommand( androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: MemoryFileSystem.test(), logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), ); try { await createTestCommandRunner(command).run(<String>[ 'build', 'test', '--${FlutterOptions.kFatalWarnings}', ]); } on Exception { fail('Unexpected exception thrown'); } }, overrides: <Type, Generator>{ FileSystem: () => fs, ProcessManager: () => FakeProcessManager.any(), }); testUsingContext("doesn't fail if --fatal-warnings not specified", () async { command = FakeBuildCommand( androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: MemoryFileSystem.test(), logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), ); testLogger.printWarning('Warning: Mild annoyance Will Robinson!'); try { await createTestCommandRunner(command).run(<String>[ 'build', 'test', ]); } on Exception { fail('Unexpected exception thrown'); } }, overrides: <Type, Generator>{ FileSystem: () => fs, ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('fails if --fatal-warnings specified and warnings emitted', () async { command = FakeBuildCommand( androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: MemoryFileSystem.test(), logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), ); testLogger.printWarning('Warning: Mild annoyance Will Robinson!'); await expectLater(createTestCommandRunner(command).run(<String>[ 'build', 'test', '--${FlutterOptions.kFatalWarnings}', ]), throwsToolExit(message: 'Logger received warning output during the run, and "--${FlutterOptions.kFatalWarnings}" is enabled.')); }, overrides: <Type, Generator>{ FileSystem: () => fs, ProcessManager: () => FakeProcessManager.any(), }); testUsingContext('fails if --fatal-warnings specified and errors emitted', () async { command = FakeBuildCommand( androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: MemoryFileSystem.test(), logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), ); testLogger.printError('Error: Danger Will Robinson!'); await expectLater(createTestCommandRunner(command).run(<String>[ 'build', 'test', '--${FlutterOptions.kFatalWarnings}', ]), throwsToolExit(message: 'Logger received error output during the run, and "--${FlutterOptions.kFatalWarnings}" is enabled.')); }, overrides: <Type, Generator>{ FileSystem: () => fs, ProcessManager: () => FakeProcessManager.any(), }); }); } class FakeBuildInfoCommand extends FlutterCommand { FakeBuildInfoCommand() : super() { addSplitDebugInfoOption(); addDartObfuscationOption(); } @override String get description => ''; @override String get name => 'fake'; @override Future<FlutterCommandResult> runCommand() async { await getBuildInfo(); return FlutterCommandResult.success(); } } class FakeBuildCommand extends BuildCommand { FakeBuildCommand({ required super.fileSystem, required super.buildSystem, required super.osUtils, required Logger logger, required super.androidSdk, bool verboseHelp = false, }) : super(logger: logger, verboseHelp: verboseHelp,) { addSubcommand(FakeBuildSubcommand(logger: logger, verboseHelp: verboseHelp)); } @override String get description => ''; @override String get name => 'build'; @override Future<FlutterCommandResult> runCommand() async { return FlutterCommandResult.success(); } } class FakeBuildSubcommand extends BuildSubCommand { FakeBuildSubcommand({required super.logger, required super.verboseHelp}); @override String get description => ''; @override String get name => 'test'; @override Future<FlutterCommandResult> runCommand() async { return FlutterCommandResult.success(); } }