Unverified Commit fde26751 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Make Pub an interface in the flutter tool (#42257)

parent fc626661
......@@ -102,7 +102,7 @@ class BuildRunner extends CodeGenerator {
stringBuffer.writeln(' build_daemon: $kSupportedBuildDaemonVersion');
syntheticPubspec.writeAsStringSync(stringBuffer.toString());
await pubGet(
await pub.get(
context: PubContext.pubGet,
directory: generatedDirectory.path,
upgrade: false,
......
......@@ -179,7 +179,7 @@ class WebFs {
// Workaround for https://github.com/flutter/flutter/issues/41681.
final String toolPath = fs.path.join(Cache.flutterRoot, 'packages', 'flutter_tools');
if (!fs.isFileSync(fs.path.join(toolPath, '.packages'))) {
await pubGet(
await pub.get(
context: PubContext.pubGet,
directory: toolPath,
offline: true,
......
......@@ -498,7 +498,7 @@ To edit platform code in an IDE see https://flutter.dev/developing-packages/#edi
templateContext['description'] = description;
generatedCount += _renderTemplate(fs.path.join('module', 'common'), directory, templateContext, overwrite: overwrite);
if (argResults['pub']) {
await pubGet(
await pub.get(
context: PubContext.create,
directory: directory.path,
offline: argResults['offline'],
......@@ -517,7 +517,7 @@ To edit platform code in an IDE see https://flutter.dev/developing-packages/#edi
templateContext['description'] = description;
generatedCount += _renderTemplate('package', directory, templateContext, overwrite: overwrite);
if (argResults['pub']) {
await pubGet(
await pub.get(
context: PubContext.createPackage,
directory: directory.path,
offline: argResults['offline'],
......@@ -534,7 +534,7 @@ To edit platform code in an IDE see https://flutter.dev/developing-packages/#edi
templateContext['description'] = description;
generatedCount += _renderTemplate('plugin', directory, templateContext, overwrite: overwrite);
if (argResults['pub']) {
await pubGet(
await pub.get(
context: PubContext.createPlugin,
directory: directory.path,
offline: argResults['offline'],
......@@ -570,7 +570,7 @@ To edit platform code in an IDE see https://flutter.dev/developing-packages/#edi
}
if (argResults['pub']) {
await pubGet(context: PubContext.create, directory: directory.path, offline: argResults['offline']);
await pub.get(context: PubContext.create, directory: directory.path, offline: argResults['offline']);
await project.ensureReadyForPlatformSpecificTooling(checkProjects: false);
}
......
......@@ -93,7 +93,7 @@ class PackagesGetCommand extends FlutterCommand {
Future<void> _runPubGet(String directory) async {
final Stopwatch pubGetTimer = Stopwatch()..start();
try {
await pubGet(context: PubContext.pubGet,
await pub.get(context: PubContext.pubGet,
directory: directory,
upgrade: upgrade ,
offline: argResults['offline'],
......@@ -164,7 +164,7 @@ class PackagesTestCommand extends FlutterCommand {
@override
Future<FlutterCommandResult> runCommand() async {
Cache.releaseLockEarly();
await pub(<String>['run', 'test', ...argResults.rest], context: PubContext.runTest, retry: false);
await pub.batch(<String>['run', 'test', ...argResults.rest], context: PubContext.runTest, retry: false);
return null;
}
}
......@@ -205,7 +205,7 @@ class PackagesPublishCommand extends FlutterCommand {
if (argResults['force']) '--force',
];
Cache.releaseLockEarly();
await pubInteractively(<String>['publish', ...args]);
await pub.interactively(<String>['publish', ...args]);
return null;
}
}
......@@ -236,7 +236,7 @@ class PackagesForwardCommand extends FlutterCommand {
@override
Future<FlutterCommandResult> runCommand() async {
Cache.releaseLockEarly();
await pubInteractively(<String>[_commandName, ...argResults.rest]);
await pub.interactively(<String>[_commandName, ...argResults.rest]);
return null;
}
......@@ -264,7 +264,7 @@ class PackagesPassthroughCommand extends FlutterCommand {
@override
Future<FlutterCommandResult> runCommand() async {
Cache.releaseLockEarly();
await pubInteractively(argResults.rest);
await pub.interactively(argResults.rest);
return null;
}
}
......@@ -131,7 +131,7 @@ class TestCommand extends FastFlutterCommand {
'directory (or one of its subdirectories).');
}
if (shouldRunPub) {
await pubGet(context: PubContext.getVerifyContext(name), skipPubspecYamlCheck: true);
await pub.get(context: PubContext.getVerifyContext(name), skipPubspecYamlCheck: true);
}
final bool buildTestAssets = argResults['test-assets'];
final List<String> names = argResults['name'];
......
......@@ -253,7 +253,7 @@ class UpdatePackagesCommand extends FlutterCommand {
fakePackage.createSync();
fakePackage.writeAsStringSync(_generateFakePubspec(dependencies.values));
// First we run "pub upgrade" on this generated package:
await pubGet(
await pub.get(
context: PubContext.updatePackages,
directory: tempDir.path,
upgrade: true,
......@@ -264,7 +264,7 @@ class UpdatePackagesCommand extends FlutterCommand {
// of all the dependencies so that we can figure out the transitive
// dependencies later. It also remembers which version was selected for
// each package.
await pub(
await pub.batch(
<String>['deps', '--style=compact'],
context: PubContext.updatePackages,
directory: tempDir.path,
......@@ -324,7 +324,7 @@ class UpdatePackagesCommand extends FlutterCommand {
int count = 0;
for (Directory dir in packages) {
await pubGet(context: PubContext.updatePackages, directory: dir.path, checkLastModified: false);
await pub.get(context: PubContext.updatePackages, directory: dir.path, checkLastModified: false);
count += 1;
}
......
......@@ -264,7 +264,7 @@ class UpgradeCommandRunner {
final String projectRoot = findProjectRoot();
if (projectRoot != null) {
printStatus('');
await pubGet(context: PubContext.pubUpgrade, directory: projectRoot, upgrade: true, checkLastModified: false);
await pub.get(context: PubContext.pubUpgrade, directory: projectRoot, upgrade: true, checkLastModified: false);
}
}
......
......@@ -119,7 +119,7 @@ class VersionCommand extends FlutterCommand {
final String projectRoot = findProjectRoot();
if (projectRoot != null) {
printStatus('');
await pubGet(
await pub.get(
context: PubContext.pubUpgrade,
directory: projectRoot,
upgrade: true,
......
......@@ -27,6 +27,7 @@ import 'base/utils.dart';
import 'build_system/build_system.dart';
import 'cache.dart';
import 'compile.dart';
import 'dart/pub.dart';
import 'devfs.dart';
import 'device.dart';
import 'doctor.dart';
......@@ -105,6 +106,7 @@ Future<T> runInContext<T>(
MacOSWorkflow: () => const MacOSWorkflow(),
MDnsObservatoryDiscovery: () => MDnsObservatoryDiscovery(),
OperatingSystemUtils: () => OperatingSystemUtils(),
Pub: () => const Pub(),
ProcessInfo: () => ProcessInfo(),
ProcessUtils: () => ProcessUtils(),
Signals: () => Signals(),
......
......@@ -7,6 +7,7 @@ import 'dart:async';
import 'package:meta/meta.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart' as io;
import '../base/logger.dart';
......@@ -19,6 +20,9 @@ import '../reporting/reporting.dart';
import '../runner/flutter_command.dart';
import 'sdk.dart';
/// The [Pub] instance.
Pub get pub => context.get<Pub>();
/// Represents Flutter-specific data that is added to the `PUB_ENVIRONMENT`
/// environment variable and allows understanding the type of requests made to
/// the package site on Flutter's behalf.
......@@ -77,9 +81,16 @@ bool _shouldRunPubGet({ File pubSpecYaml, File dotPackages }) {
return false;
}
/// [context] provides extra information to package server requests to
/// understand usage.
Future<void> pubGet({
/// A handle for interacting with the pub tool.
abstract class Pub {
/// Create a default [Pub] instance.
const factory Pub() = _DefaultPub;
/// Runs `pub get`.
///
/// [context] provides extra information to package server requests to
/// understand usage.
Future<void> get({
@required PubContext context,
String directory,
bool skipIfAbsent = false,
......@@ -87,7 +98,54 @@ Future<void> pubGet({
bool offline = false,
bool checkLastModified = true,
bool skipPubspecYamlCheck = false,
}) async {
});
/// Runs pub in 'batch' mode.
///
/// forwarding complete lines written by pub to its stdout/stderr streams to
/// the corresponding stream of this process, optionally applying filtering.
/// The pub process will not receive anything on its stdin stream.
///
/// The `--trace` argument is passed to `pub` (by mutating the provided
/// `arguments` list) when `showTraceForErrors` is true, and when `showTraceForErrors`
/// is null/unset, and `isRunningOnBot` is true.
///
/// [context] provides extra information to package server requests to
/// understand usage.
Future<void> batch(
List<String> arguments, {
@required PubContext context,
String directory,
MessageFilter filter,
String failureMessage = 'pub failed',
@required bool retry,
bool showTraceForErrors,
});
/// Runs pub in 'interactive' mode.
///
/// directly piping the stdin stream of this process to that of pub, and the
/// stdout/stderr stream of pub to the corresponding streams of this process.
Future<void> interactively(
List<String> arguments, {
String directory,
});
}
class _DefaultPub implements Pub {
const _DefaultPub();
@override
Future<void> get({
@required PubContext context,
String directory,
bool skipIfAbsent = false,
bool upgrade = false,
bool offline = false,
bool checkLastModified = true,
bool skipPubspecYamlCheck = false,
}) async {
directory ??= fs.currentDirectory.path;
final File pubSpecYaml = fs.file(fs.path.join(directory, 'pubspec.yaml'));
......@@ -113,7 +171,7 @@ Future<void> pubGet({
if (offline) '--offline',
];
try {
await pub(
await batch(
args,
context: context,
directory: directory,
......@@ -137,21 +195,11 @@ Future<void> pubGet({
'(pubspec.yaml timestamp: ${pubSpecYaml.lastModifiedSync()}; '
'.packages timestamp: ${dotPackages.lastModifiedSync()}).');
}
}
}
typedef MessageFilter = String Function(String message);
/// Runs pub in 'batch' mode, forwarding complete lines written by pub to its
/// stdout/stderr streams to the corresponding stream of this process, optionally
/// applying filtering. The pub process will not receive anything on its stdin stream.
///
/// The `--trace` argument is passed to `pub` (by mutating the provided
/// `arguments` list) when `showTraceForErrors` is true, and when `showTraceForErrors`
/// is null/unset, and `isRunningOnBot` is true.
///
/// [context] provides extra information to package server requests to
/// understand usage.
Future<void> pub(
@override
Future<void> batch(
List<String> arguments, {
@required PubContext context,
String directory,
......@@ -159,7 +207,7 @@ Future<void> pub(
String failureMessage = 'pub failed',
@required bool retry,
bool showTraceForErrors,
}) async {
}) async {
showTraceForErrors ??= isRunningOnBot;
bool versionSolvingFailed = false;
......@@ -213,15 +261,13 @@ Future<void> pub(
if (code != 0) {
throwToolExit('$failureMessage ($code)', exitCode: code);
}
}
}
/// Runs pub in 'interactive' mode, directly piping the stdin stream of this
/// process to that of pub, and the stdout/stderr stream of pub to the corresponding
/// streams of this process.
Future<void> pubInteractively(
@override
Future<void> interactively(
List<String> arguments, {
String directory,
}) async {
}) async {
Cache.releaseLockEarly();
final io.Process process = await processUtils.start(
_pubCommand(arguments),
......@@ -243,13 +289,17 @@ Future<void> pubInteractively(
if (code != 0) {
throwToolExit('pub finished with exit code $code', exitCode: code);
}
}
}
/// The command used for running pub.
List<String> _pubCommand(List<String> arguments) {
/// The command used for running pub.
List<String> _pubCommand(List<String> arguments) {
return <String>[sdkBinaryName('pub'), ...arguments];
}
}
typedef MessageFilter = String Function(String message);
/// The full environment used when running pub.
///
/// [context] provides extra information to package server requests to
......
......@@ -538,7 +538,7 @@ abstract class FlutterCommand extends Command<void> {
}
if (shouldRunPub) {
await pubGet(context: PubContext.getVerifyContext(name));
await pub.get(context: PubContext.getVerifyContext(name));
final FlutterProject project = FlutterProject.current();
await project.ensureReadyForPlatformSpecificTooling(checkProjects: true);
}
......
......@@ -32,7 +32,7 @@ void main() {
testUsingContext('AnalysisServer success', () async {
_createSampleProject(tempDir);
await pubGet(context: PubContext.flutterTests, directory: tempDir.path);
await pub.get(context: PubContext.flutterTests, directory: tempDir.path);
server = AnalysisServer(dartSdkPath, <String>[tempDir.path]);
......@@ -46,13 +46,14 @@ void main() {
expect(errorCount, 0);
}, overrides: <Type, Generator>{
OperatingSystemUtils: () => os,
Pub: () => const Pub(),
});
});
testUsingContext('AnalysisServer errors', () async {
_createSampleProject(tempDir, brokenCode: true);
await pubGet(context: PubContext.flutterTests, directory: tempDir.path);
await pub.get(context: PubContext.flutterTests, directory: tempDir.path);
server = AnalysisServer(dartSdkPath, <String>[tempDir.path]);
......@@ -68,6 +69,7 @@ void main() {
expect(errorCount, greaterThan(0));
}, overrides: <Type, Generator>{
OperatingSystemUtils: () => os,
Pub: () => const Pub(),
});
testUsingContext('Returns no errors when source is error-free', () async {
......@@ -85,6 +87,7 @@ void main() {
expect(errorCount, 0);
}, overrides: <Type, Generator>{
OperatingSystemUtils: () => os,
Pub: () => const Pub(),
});
}
......
......@@ -11,6 +11,7 @@ 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/commands/build_web.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/project.dart';
......@@ -44,6 +45,7 @@ void main() {
Platform: () => mockPlatform,
FlutterVersion: () => MockFlutterVersion(),
FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
Pub: () => MockPub(),
});
});
......@@ -145,7 +147,6 @@ class UrlLauncherPlugin {}
when(buildSystem.build(any, any)).thenAnswer((Invocation invocation) async {
return BuildResult(success: true);
});
await runner.run(<String>['build', 'web']);
expect(fs.file(fs.path.join('lib', 'generated_plugin_registrant.dart')).existsSync(), true);
......@@ -179,3 +180,4 @@ class MockFlutterVersion extends Mock implements FlutterVersion {
@override
bool get isMaster => true;
}
class MockPub extends Mock implements Pub {}
......@@ -73,6 +73,7 @@ void main() {
final List<String> args = <String>[
'drive',
'--target=$testApp',
'--no-pub',
];
try {
await createTestCommandRunner(command).run(args);
......@@ -99,6 +100,7 @@ void main() {
final List<String> args = <String>[
'drive',
'--target=$testApp',
'--no-pub',
];
try {
await createTestCommandRunner(command).run(args);
......@@ -118,6 +120,7 @@ void main() {
'--no-wrap',
'drive',
'--target=$appFile',
'--no-pub',
];
try {
await createTestCommandRunner(command).run(args);
......@@ -139,6 +142,7 @@ void main() {
'--no-wrap',
'drive',
'--target=$appFile',
'--no-pub',
];
try {
await createTestCommandRunner(command).run(args);
......@@ -178,6 +182,7 @@ void main() {
final List<String> args = <String>[
'drive',
'--target=$testApp',
'--no-pub',
];
await createTestCommandRunner(command).run(args);
expect(testLogger.errorText, isEmpty);
......@@ -208,6 +213,7 @@ void main() {
final List<String> args = <String>[
'drive',
'--target=$testApp',
'--no-pub',
];
try {
await createTestCommandRunner(command).run(args);
......@@ -365,6 +371,7 @@ void main() {
final List<String> args = <String>[
'drive',
'--target=$testApp',
'--no-pub',
];
try {
await createTestCommandRunner(command).run(args);
......@@ -391,6 +398,7 @@ void main() {
'drive',
'--build',
'--target=$testApp',
'--no-pub',
];
try {
await createTestCommandRunner(command).run(args);
......@@ -417,6 +425,7 @@ void main() {
'drive',
'--no-build',
'--target=$testApp',
'--no-pub',
];
try {
await createTestCommandRunner(command).run(args);
......
......@@ -36,7 +36,7 @@ void main() {
final RunCommand command = RunCommand();
applyMocksToCommand(command);
try {
await createTestCommandRunner(command).run(<String>['run', '-t', 'abc123']);
await createTestCommandRunner(command).run(<String>['run', '-t', 'abc123', '--no-pub']);
fail('Expect exception');
} on ToolExit catch (e) {
expect(e.exitCode ?? 1, 1);
......@@ -61,6 +61,7 @@ void main() {
'run',
'--dart-flags', '"--observe"',
'--no-hot',
'--no-pub',
];
});
......
......@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/version.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
......@@ -30,6 +31,7 @@ void main() {
expect(testLogger.statusText, equals('v10.0.0\r\nv20.0.0\n' ''));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Pub: () => const Pub(),
});
testUsingContext('version switch', () async {
......@@ -40,6 +42,7 @@ void main() {
expect(testLogger.statusText, contains('Switching Flutter to version $version'));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Pub: () => const Pub(),
});
testUsingContext('switch to not supported version without force', () async {
......@@ -50,6 +53,7 @@ void main() {
expect(testLogger.errorText, contains('Version command is not supported in'));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Pub: () => const Pub(),
});
testUsingContext('switch to not supported version with force', () async {
......@@ -60,6 +64,7 @@ void main() {
expect(testLogger.statusText, contains('Switching Flutter to version $version with force'));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Pub: () => const Pub(),
});
testUsingContext('tool exit on confusing version', () async {
......@@ -70,6 +75,7 @@ void main() {
throwsA(isInstanceOf<ToolExit>()));
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(),
Pub: () => const Pub(),
});
testUsingContext('exit tool if can\'t get the tags', () async {
......
......@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/analyze.dart';
import 'package:flutter_tools/src/commands/create.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import '../../src/common.dart';
......@@ -53,7 +54,9 @@ void main() {
],
);
expect(libMain.existsSync(), isTrue);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
// Analyze in the current directory - no arguments
testUsingContext('working directory', () async {
......@@ -62,7 +65,9 @@ void main() {
arguments: <String>['analyze'],
statusTextContains: <String>['No issues found!'],
);
}, timeout: allowForSlowAnalyzeTests);
}, timeout: allowForSlowAnalyzeTests, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
// Analyze a specific file outside the current directory
testUsingContext('passing one file throws', () async {
......@@ -72,8 +77,9 @@ void main() {
toolExit: true,
exitMessageContains: 'is not a directory',
);
}, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
// Analyze in the current directory - no arguments
testUsingContext('working directory with errors', () async {
// Break the code to produce the "The parameter 'onPressed' is required" hint
......@@ -104,7 +110,10 @@ void main() {
exitMessageContains: '2 issues found.',
toolExit: true,
);
}, timeout: allowForSlowAnalyzeTests, overrides: noColorTerminalOverride);
}, timeout: allowForSlowAnalyzeTests, overrides: <Type, Generator>{
Pub: () => const Pub(),
...noColorTerminalOverride,
});
// Analyze in the current directory - no arguments
testUsingContext('working directory with local options', () async {
......@@ -131,7 +140,10 @@ void main() {
exitMessageContains: '3 issues found.',
toolExit: true,
);
}, timeout: allowForSlowAnalyzeTests, overrides: noColorTerminalOverride);
}, timeout: allowForSlowAnalyzeTests, overrides: <Type, Generator>{
Pub: () => const Pub(),
...noColorTerminalOverride
});
testUsingContext('no duplicate issues', () async {
final Directory tempDir = fs.systemTempDirectory.createTempSync('flutter_analyze_once_test_2.').absolute;
......@@ -165,7 +177,10 @@ void bar() {
} finally {
tryToDelete(tempDir);
}
}, overrides: noColorTerminalOverride);
}, overrides: <Type, Generator>{
Pub: () => const Pub(),
...noColorTerminalOverride
});
testUsingContext('returns no issues when source is error-free', () async {
const String contents = '''
......@@ -182,7 +197,10 @@ StringBuffer bar = StringBuffer('baz');
} finally {
tryToDelete(tempDir);
}
}, overrides: noColorTerminalOverride);
}, overrides: <Type, Generator>{
Pub: () => const Pub(),
...noColorTerminalOverride
});
testUsingContext('returns no issues for todo comments', () async {
const String contents = '''
......@@ -200,7 +218,10 @@ StringBuffer bar = StringBuffer('baz');
} finally {
tryToDelete(tempDir);
}
}, overrides: noColorTerminalOverride);
}, overrides: <Type, Generator>{
Pub: () => const Pub(),
...noColorTerminalOverride
});
});
}
......
......@@ -59,6 +59,7 @@ void main() {
'bundle',
...?arguments,
'--target=$projectPath/lib/main.dart',
'--no-pub'
]);
return command;
}
......
......@@ -13,6 +13,7 @@ import 'package:flutter_tools/src/base/net.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/create.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/dart/sdk.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/version.dart';
......@@ -77,7 +78,9 @@ void main() {
],
);
return _runFlutterTest(projectDir);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('can create a default project if empty directory exists', () async {
await projectDir.create(recursive: true);
......@@ -93,7 +96,9 @@ void main() {
'ios/Runner/GeneratedPluginRegistrant.h',
],
);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('creates a module project correctly', () async {
await _createAndAnalyzeProject(projectDir, <String>[
......@@ -114,7 +119,9 @@ void main() {
]);
return _runFlutterTest(projectDir);
},
timeout: allowForRemotePubInvocation,
timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
},
);
testUsingContext('cannot create a project if non-empty non-project directory exists with .metadata', () async {
......@@ -131,7 +138,10 @@ void main() {
'.ios/',
]),
throwsToolExit(message: 'Sorry, unable to detect the type of project to recreate'));
}, timeout: allowForRemotePubInvocation, overrides: noColorTerminalOverride);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
...noColorTerminalOverride,
});
testUsingContext('Will create an app project if non-empty non-project directory exists without .metadata', () async {
await projectDir.absolute.childDirectory('blag').create(recursive: true);
......@@ -154,7 +164,9 @@ void main() {
'.ios/',
],
);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('detects and recreates an app project correctly', () async {
await projectDir.absolute.childDirectory('lib').create(recursive: true);
......@@ -177,7 +189,9 @@ void main() {
'.ios/',
],
);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('detects and recreates a plugin project correctly', () async {
await projectDir.create(recursive: true);
......@@ -200,7 +214,9 @@ void main() {
'lib/flutter_project.dart',
],
);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('detects and recreates a package project correctly', () async {
await projectDir.create(recursive: true);
......@@ -229,7 +245,9 @@ void main() {
'test/widget_test.dart',
],
);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('kotlin/swift legacy app project', () async {
return _createProject(
......@@ -249,7 +267,9 @@ void main() {
'ios/Runner/main.m',
],
);
}, timeout: allowForCreateFlutterProject);
}, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('can create a package project', () async {
await _createAndAnalyzeProject(
......@@ -277,7 +297,9 @@ void main() {
],
);
return _runFlutterTest(projectDir);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('can create a plugin project', () async {
await _createAndAnalyzeProject(
......@@ -297,7 +319,9 @@ void main() {
],
);
return _runFlutterTest(projectDir.childDirectory('example'));
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('kotlin/swift plugin project', () async {
return _createProject(
......@@ -380,7 +404,9 @@ void main() {
<String>['--with-driver-test', '--template=app'],
<String>['lib/main.dart'],
);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('module project with pub', () async {
return _createProject(projectDir, <String>[
......@@ -413,7 +439,9 @@ void main() {
'android/',
'ios/',
]);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('androidx is used by default in an app project', () async {
......@@ -902,7 +930,9 @@ void main() {
'.android/app/src/main/java/com/bar/foo/flutter_project/host/MainActivity.java',
],
);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('can re-gen module .ios/ folder, reusing custom org', () async {
await _createProject(
......@@ -917,7 +947,9 @@ void main() {
await project.ios.productBundleIdentifier,
'com.bar.foo.flutterProject',
);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('can re-gen app android/ folder, reusing custom org', () async {
await _createProject(
......@@ -1070,6 +1102,8 @@ void main() {
'ios/Runner/GeneratedPluginRegistrant.h',
],
);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('fails when invalid package name', () async {
......@@ -1097,6 +1131,7 @@ void main() {
timeout: allowForCreateFlutterProject,
overrides: <Type, Generator>{
ProcessManager: () => loggingProcessManager,
Pub: () => const Pub(),
},
);
......@@ -1115,6 +1150,7 @@ void main() {
timeout: allowForCreateFlutterProject,
overrides: <Type, Generator>{
ProcessManager: () => loggingProcessManager,
Pub: () => const Pub(),
},
);
......
......@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/utils.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/packages.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:process/process.dart';
......@@ -206,7 +207,9 @@ void main() {
expectDependenciesResolved(projectPath);
expectZeroPluginsInjected(projectPath);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('get --offline fetches packages', () async {
final String projectPath = await createProject(tempDir,
......@@ -217,7 +220,9 @@ void main() {
expectDependenciesResolved(projectPath);
expectZeroPluginsInjected(projectPath);
}, timeout: allowForCreateFlutterProject);
}, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('set the number of plugins as usage value', () async {
final String projectPath = await createProject(tempDir,
......@@ -229,7 +234,9 @@ void main() {
expect(await getCommand.usageValues,
containsPair(CustomDimensions.commandPackagesNumberPlugins, '0'));
}, timeout: allowForCreateFlutterProject);
}, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('indicate that the project is not a module in usage value', () async {
final String projectPath = await createProject(tempDir,
......@@ -241,7 +248,9 @@ void main() {
expect(await getCommand.usageValues,
containsPair(CustomDimensions.commandPackagesProjectModule, 'false'));
}, timeout: allowForCreateFlutterProject);
}, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('indicate that the project is a module in usage value', () async {
final String projectPath = await createProject(tempDir,
......@@ -253,7 +262,9 @@ void main() {
expect(await getCommand.usageValues,
containsPair(CustomDimensions.commandPackagesProjectModule, 'true'));
}, timeout: allowForCreateFlutterProject);
}, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('upgrade fetches packages', () async {
final String projectPath = await createProject(tempDir,
......@@ -264,7 +275,9 @@ void main() {
expectDependenciesResolved(projectPath);
expectZeroPluginsInjected(projectPath);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('get fetches packages and injects plugin', () async {
final String projectPath = await createProjectWithPlugin('path_provider',
......@@ -275,7 +288,9 @@ void main() {
expectDependenciesResolved(projectPath);
expectModulePluginInjected(projectPath);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
testUsingContext('get fetches packages and injects plugin in plugin project', () async {
final String projectPath = await createProject(
......@@ -294,7 +309,9 @@ void main() {
expectDependenciesResolved(exampleProjectPath);
expectPluginInjected(exampleProjectPath);
}, timeout: allowForRemotePubInvocation);
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
Pub: () => const Pub(),
});
});
group('packages test/pub', () {
......@@ -317,6 +334,7 @@ void main() {
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
BotDetector: () => const AlwaysFalseBotDetector(),
Pub: () => const Pub(),
});
testUsingContext('test with bot', () async {
......@@ -331,6 +349,7 @@ void main() {
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
BotDetector: () => const AlwaysTrueBotDetector(),
Pub: () => const Pub(),
});
testUsingContext('run', () async {
......@@ -344,6 +363,7 @@ void main() {
}, overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
Pub: () => const Pub(),
});
testUsingContext('pub publish', () async {
......@@ -368,6 +388,7 @@ void main() {
}, overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
Pub: () => const Pub(),
});
testUsingContext('publish', () async {
......@@ -380,6 +401,7 @@ void main() {
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
BotDetector: () => const AlwaysTrueBotDetector(),
Pub: () => const Pub(),
});
testUsingContext('packages publish', () async {
......@@ -392,6 +414,7 @@ void main() {
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
BotDetector: () => const AlwaysTrueBotDetector(),
Pub: () => const Pub(),
});
testUsingContext('deps', () async {
......@@ -404,6 +427,7 @@ void main() {
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
BotDetector: () => const AlwaysTrueBotDetector(),
Pub: () => const Pub(),
});
testUsingContext('cache', () async {
......@@ -416,6 +440,7 @@ void main() {
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
BotDetector: () => const AlwaysTrueBotDetector(),
Pub: () => const Pub(),
});
testUsingContext('version', () async {
......@@ -428,6 +453,7 @@ void main() {
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
BotDetector: () => const AlwaysTrueBotDetector(),
Pub: () => const Pub(),
});
testUsingContext('uploader', () async {
......@@ -440,6 +466,7 @@ void main() {
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
BotDetector: () => const AlwaysTrueBotDetector(),
Pub: () => const Pub(),
});
testUsingContext('global', () async {
......@@ -453,6 +480,7 @@ void main() {
ProcessManager: () => mockProcessManager,
Stdio: () => mockStdio,
BotDetector: () => const AlwaysTrueBotDetector(),
Pub: () => const Pub(),
});
});
}
......@@ -40,6 +40,7 @@ void main() {
final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[
'aar',
'--no-pub',
...?arguments,
target,
]);
......
......@@ -324,6 +324,7 @@ Future<BuildApkCommand> runBuildApkCommand(
await runner.run(<String>[
'apk',
...?arguments,
'--no-pub',
fs.path.join(target, 'lib', 'main.dart'),
]);
return command;
......
......@@ -315,6 +315,7 @@ Future<BuildAppBundleCommand> runBuildAppBundleCommand(
await runner.run(<String>[
'appbundle',
...?arguments,
'--no-pub',
fs.path.join(target, 'lib', 'main.dart'),
]);
return command;
......
......@@ -36,7 +36,7 @@ void main() {
FakeAsync().run((FakeAsync time) {
expect(processMock.lastPubEnvironment, isNull);
expect(testLogger.statusText, '');
pubGet(context: PubContext.flutterTests, checkLastModified: false).then((void value) {
pub.get(context: PubContext.flutterTests, checkLastModified: false).then((void value) {
error = 'test completed unexpectedly';
}, onError: (dynamic thrownError) {
error = 'test failed unexpectedly: $thrownError';
......@@ -94,6 +94,7 @@ void main() {
Platform: () => FakePlatform(
environment: UnmodifiableMapView<String, String>(<String, String>{}),
),
Pub: () => const Pub(),
});
testUsingContext('pub cache in root is used', () async {
......@@ -106,7 +107,7 @@ void main() {
MockDirectory.findCache = true;
expect(processMock.lastPubEnvironment, isNull);
expect(processMock.lastPubCache, isNull);
pubGet(context: PubContext.flutterTests, checkLastModified: false).then((void value) {
pub.get(context: PubContext.flutterTests, checkLastModified: false).then((void value) {
error = 'test completed unexpectedly';
}, onError: (dynamic thrownError) {
error = 'test failed unexpectedly: $thrownError';
......@@ -121,6 +122,7 @@ void main() {
Platform: () => FakePlatform(
environment: UnmodifiableMapView<String, String>(<String, String>{}),
),
Pub: () => const Pub(),
});
testUsingContext('pub cache in environment is used', () async {
......@@ -132,7 +134,7 @@ void main() {
MockDirectory.findCache = true;
expect(processMock.lastPubEnvironment, isNull);
expect(processMock.lastPubCache, isNull);
pubGet(context: PubContext.flutterTests, checkLastModified: false).then((void value) {
pub.get(context: PubContext.flutterTests, checkLastModified: false).then((void value) {
error = 'test completed unexpectedly';
}, onError: (dynamic thrownError) {
error = 'test failed unexpectedly: $thrownError';
......@@ -149,11 +151,12 @@ void main() {
'PUB_CACHE': 'custom/pub-cache/path',
}),
),
Pub: () => const Pub(),
});
testUsingContext('analytics sent on success', () async {
MockDirectory.findCache = true;
await pubGet(context: PubContext.flutterTests, checkLastModified: false);
await pub.get(context: PubContext.flutterTests, checkLastModified: false);
verify(flutterUsage.sendEvent('pub-result', 'flutter-tests', label: 'success')).called(1);
}, overrides: <Type, Generator>{
ProcessManager: () => MockProcessManager(0),
......@@ -164,12 +167,13 @@ void main() {
}),
),
Usage: () => MockUsage(),
Pub: () => const Pub(),
});
testUsingContext('analytics sent on failure', () async {
MockDirectory.findCache = true;
try {
await pubGet(context: PubContext.flutterTests, checkLastModified: false);
await pub.get(context: PubContext.flutterTests, checkLastModified: false);
} on ToolExit {
// Ignore.
}
......@@ -183,12 +187,13 @@ void main() {
}),
),
Usage: () => MockUsage(),
Pub: () => const Pub(),
});
testUsingContext('analytics sent on failed version solve', () async {
MockDirectory.findCache = true;
try {
await pubGet(context: PubContext.flutterTests, checkLastModified: false);
await pub.get(context: PubContext.flutterTests, checkLastModified: false);
} on ToolExit {
// Ignore.
}
......@@ -205,6 +210,7 @@ void main() {
}),
),
Usage: () => MockUsage(),
Pub: () => const Pub(),
});
}
......
......@@ -44,7 +44,7 @@ void main() {
}
''');
await pubGet(context: PubContext.flutterTests, directory: projectDirectory.path);
await pub.get(context: PubContext.flutterTests, directory: projectDirectory.path);
final AnalysisServer server = AnalysisServer(dartSdkPath, <String>[projectDirectory.path]);
try {
final int errorCount = await analyze(server);
......
......@@ -11,7 +11,7 @@ import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/web/chrome.dart';
import 'package:flutter_tools/src/build_runner/web_fs.dart';
......@@ -89,6 +89,7 @@ void main() {
fs.file('.packages').createSync();
},
overrides: <Type, Generator>{
Pub: () => MockPub(),
OperatingSystemUtils: () => mockOperatingSystemUtils,
BuildDaemonCreator: () => mockBuildDaemonCreator,
ChromeLauncher: () => mockChromeLauncher,
......@@ -128,10 +129,13 @@ void main() {
);
// Since the .packages file is missing in the memory filesystem, this should
// be called.
verify(processUtils.stream(any,
workingDirectory: fs.path.join(Cache.flutterRoot, 'packages', 'flutter_tools'),
mapFunction: anyNamed('mapFunction'),
environment: anyNamed('environment'),)).called(1);
verify(pub.get(
context: PubContext.pubGet,
directory: anyNamed('directory'),
offline: true,
skipPubspecYamlCheck: true,
checkLastModified: false,
)).called(1);
// The build daemon is told to build once.
verify(mockBuildDaemonClient.startBuild()).called(1);
......@@ -213,3 +217,4 @@ class MockHttpMultiServer extends Mock implements HttpMultiServer {}
class MockChromeLauncher extends Mock implements ChromeLauncher {}
class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
class MockProcessUtils extends Mock implements ProcessUtils {}
class MockPub extends Mock implements Pub {}
......@@ -17,6 +17,7 @@ import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/context_runner.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/ios/plist_parser.dart';
......@@ -29,6 +30,7 @@ import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'common.dart';
import 'testbed.dart';
export 'package:flutter_tools/src/base/context.dart' show Generator;
......@@ -92,6 +94,7 @@ void testUsingContext(
TimeoutConfiguration: () => const TimeoutConfiguration(),
PlistParser: () => FakePlistParser(),
Signals: () => FakeSignals(),
Pub: () => ThrowingPub() // prevent accidentally using pub.
},
body: () {
final String flutterRoot = getFlutterRoot();
......
......@@ -18,6 +18,7 @@ import 'package:flutter_tools/src/base/signals.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/context_runner.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/version.dart';
......@@ -37,6 +38,7 @@ final Map<Type, Generator> _testbedDefaults = <Type, Generator>{
Usage: () => NoOpUsage(), // prevent addition of analytics from burdening test mocks
FlutterVersion: () => FakeFlutterVersion(), // prevent requirement to mock git for test runner.
Signals: () => FakeSignals(), // prevent registering actual signal handlers.
Pub: () => ThrowingPub(), // prevent accidental invocations of pub.
};
/// Manages interaction with the tool injection and runner system.
......@@ -711,3 +713,35 @@ class TestFeatureFlags implements FeatureFlags {
@override
final bool isNewAndroidEmbeddingEnabled;
}
class ThrowingPub implements Pub {
@override
Future<void> batch(List<String> arguments, {
PubContext context,
String directory,
MessageFilter filter,
String failureMessage = 'pub failed',
bool retry,
bool showTraceForErrors,
}) {
throw UnsupportedError('Attempted to inovke pub during test.');
}
@override
Future<void> get({
PubContext context,
String directory,
bool skipIfAbsent = false,
bool upgrade = false,
bool offline = false,
bool checkLastModified = true,
bool skipPubspecYamlCheck = false,
}) {
throw UnsupportedError('Attempted to inovke pub during test.');
}
@override
Future<void> interactively(List<String> arguments, {String directory}) {
throw UnsupportedError('Attempted to inovke pub during test.');
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment