mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

All temporary directory start with `flutter_` and have their random component separated from the name by a period, as in `flutter_test_bundle.YFYQMY`. I've tried to find some of the places where we didn't cleanly delete temporary directories, too. This greatly reduces, though it does not entirely eliminate, the directories we leave behind when running tests, especially `flutter_tools` tests. While I was at it I standardized on `tempDir` as the variable name for temporary directories, since it was the most common, removing occurrences of `temp` and `tmp`, among others. Also I factored out some common code that used to catch exceptions that happen on Windows, and made more places use that pattern.
305 lines
11 KiB
Dart
305 lines
11 KiB
Dart
// Copyright 2016 The Chromium 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 'dart:async';
|
|
|
|
import 'package:args/command_runner.dart';
|
|
import 'package:flutter_tools/src/base/file_system.dart' hide IOSink;
|
|
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:process/process.dart';
|
|
|
|
import '../src/common.dart';
|
|
import '../src/context.dart';
|
|
import '../src/mocks.dart' show MockProcessManager, MockStdio, PromptingProcess;
|
|
|
|
class AlwaysTrueBotDetector implements BotDetector {
|
|
const AlwaysTrueBotDetector();
|
|
|
|
@override
|
|
bool get isRunningOnBot => true;
|
|
}
|
|
|
|
|
|
class AlwaysFalseBotDetector implements BotDetector {
|
|
const AlwaysFalseBotDetector();
|
|
|
|
@override
|
|
bool get isRunningOnBot => false;
|
|
}
|
|
|
|
|
|
void main() {
|
|
Cache.disableLocking();
|
|
group('packages get/upgrade', () {
|
|
Directory tempDir;
|
|
|
|
setUp(() {
|
|
tempDir = fs.systemTempDirectory.createTempSync('flutter_tools_packages_test.');
|
|
});
|
|
|
|
tearDown(() {
|
|
tryToDelete(tempDir);
|
|
});
|
|
|
|
Future<String> createProjectWithPlugin(String plugin) async {
|
|
final String projectPath = await createProject(tempDir);
|
|
final File pubspec = fs.file(fs.path.join(projectPath, 'pubspec.yaml'));
|
|
String content = await pubspec.readAsString();
|
|
content = content.replaceFirst(
|
|
'\ndependencies:\n',
|
|
'\ndependencies:\n $plugin:\n',
|
|
);
|
|
await pubspec.writeAsString(content, flush: true);
|
|
return projectPath;
|
|
}
|
|
|
|
Future<Null> runCommandIn(String projectPath, String verb, { List<String> args }) async {
|
|
final PackagesCommand command = new PackagesCommand();
|
|
final CommandRunner<Null> runner = createTestCommandRunner(command);
|
|
|
|
final List<String> commandArgs = <String>['packages', verb];
|
|
if (args != null)
|
|
commandArgs.addAll(args);
|
|
commandArgs.add(projectPath);
|
|
|
|
await runner.run(commandArgs);
|
|
}
|
|
|
|
void expectExists(String projectPath, String relPath) {
|
|
expect(
|
|
fs.isFileSync(fs.path.join(projectPath, relPath)),
|
|
true,
|
|
reason: '$projectPath/$relPath should exist, but does not',
|
|
);
|
|
}
|
|
|
|
void expectContains(String projectPath, String relPath, String substring) {
|
|
expectExists(projectPath, relPath);
|
|
expect(
|
|
fs.file(fs.path.join(projectPath, relPath)).readAsStringSync(),
|
|
contains(substring),
|
|
reason: '$projectPath/$relPath has unexpected content'
|
|
);
|
|
}
|
|
|
|
void expectNotExists(String projectPath, String relPath) {
|
|
expect(
|
|
fs.isFileSync(fs.path.join(projectPath, relPath)),
|
|
false,
|
|
reason: '$projectPath/$relPath should not exist, but does',
|
|
);
|
|
}
|
|
|
|
void expectNotContains(String projectPath, String relPath, String substring) {
|
|
expectExists(projectPath, relPath);
|
|
expect(
|
|
fs.file(fs.path.join(projectPath, relPath)).readAsStringSync(),
|
|
isNot(contains(substring)),
|
|
reason: '$projectPath/$relPath has unexpected content',
|
|
);
|
|
}
|
|
|
|
const List<String> pubOutput = <String>[
|
|
'.packages',
|
|
'pubspec.lock',
|
|
];
|
|
|
|
const List<String> pluginRegistrants = <String>[
|
|
'ios/Runner/GeneratedPluginRegistrant.h',
|
|
'ios/Runner/GeneratedPluginRegistrant.m',
|
|
'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
|
|
];
|
|
|
|
const List<String> pluginWitnesses = <String>[
|
|
'.flutter-plugins',
|
|
'ios/Podfile',
|
|
];
|
|
|
|
const Map<String, String> pluginContentWitnesses = <String, String>{
|
|
'ios/Flutter/Debug.xcconfig': '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"',
|
|
'ios/Flutter/Release.xcconfig': '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"',
|
|
};
|
|
|
|
void expectDependenciesResolved(String projectPath) {
|
|
for (String output in pubOutput) {
|
|
expectExists(projectPath, output);
|
|
}
|
|
}
|
|
|
|
void expectZeroPluginsInjected(String projectPath) {
|
|
for (final String registrant in pluginRegistrants) {
|
|
expectExists(projectPath, registrant);
|
|
}
|
|
for (final String witness in pluginWitnesses) {
|
|
expectNotExists(projectPath, witness);
|
|
}
|
|
pluginContentWitnesses.forEach((String witness, String content) {
|
|
expectNotContains(projectPath, witness, content);
|
|
});
|
|
}
|
|
|
|
void expectPluginInjected(String projectPath) {
|
|
for (final String registrant in pluginRegistrants) {
|
|
expectExists(projectPath, registrant);
|
|
}
|
|
for (final String witness in pluginWitnesses) {
|
|
expectExists(projectPath, witness);
|
|
}
|
|
pluginContentWitnesses.forEach((String witness, String content) {
|
|
expectContains(projectPath, witness, content);
|
|
});
|
|
}
|
|
|
|
void removeGeneratedFiles(String projectPath) {
|
|
final Iterable<String> allFiles = <List<String>>[
|
|
pubOutput,
|
|
pluginRegistrants,
|
|
pluginWitnesses,
|
|
].expand((List<String> list) => list);
|
|
for (String path in allFiles) {
|
|
final File file = fs.file(fs.path.join(projectPath, path));
|
|
if (file.existsSync())
|
|
file.deleteSync();
|
|
}
|
|
}
|
|
|
|
testUsingContext('get fetches packages', () async {
|
|
final String projectPath = await createProject(tempDir);
|
|
removeGeneratedFiles(projectPath);
|
|
|
|
await runCommandIn(projectPath, 'get');
|
|
|
|
expectDependenciesResolved(projectPath);
|
|
expectZeroPluginsInjected(projectPath);
|
|
}, timeout: allowForRemotePubInvocation);
|
|
|
|
testUsingContext('get --offline fetches packages', () async {
|
|
final String projectPath = await createProject(tempDir);
|
|
removeGeneratedFiles(projectPath);
|
|
|
|
await runCommandIn(projectPath, 'get', args: <String>['--offline']);
|
|
|
|
expectDependenciesResolved(projectPath);
|
|
expectZeroPluginsInjected(projectPath);
|
|
}, timeout: allowForCreateFlutterProject);
|
|
|
|
testUsingContext('upgrade fetches packages', () async {
|
|
final String projectPath = await createProject(tempDir);
|
|
removeGeneratedFiles(projectPath);
|
|
|
|
await runCommandIn(projectPath, 'upgrade');
|
|
|
|
expectDependenciesResolved(projectPath);
|
|
expectZeroPluginsInjected(projectPath);
|
|
}, timeout: allowForRemotePubInvocation);
|
|
|
|
testUsingContext('get fetches packages and injects plugin', () async {
|
|
final String projectPath = await createProjectWithPlugin('path_provider');
|
|
removeGeneratedFiles(projectPath);
|
|
|
|
await runCommandIn(projectPath, 'get');
|
|
|
|
expectDependenciesResolved(projectPath);
|
|
expectPluginInjected(projectPath);
|
|
// TODO(mravn): This test fails on the Chrome windows bot only.
|
|
// Skipping until resolved.
|
|
}, timeout: allowForRemotePubInvocation, skip: true);
|
|
testUsingContext('get fetches packages and injects plugin in plugin project', () async {
|
|
final String projectPath = await createProject(
|
|
tempDir,
|
|
arguments: <String>['-t', 'plugin', '--no-pub'],
|
|
);
|
|
final String exampleProjectPath = fs.path.join(projectPath, 'example');
|
|
removeGeneratedFiles(projectPath);
|
|
removeGeneratedFiles(exampleProjectPath);
|
|
|
|
await runCommandIn(projectPath, 'get');
|
|
|
|
expectDependenciesResolved(projectPath);
|
|
|
|
await runCommandIn(exampleProjectPath, 'get');
|
|
|
|
expectDependenciesResolved(exampleProjectPath);
|
|
expectPluginInjected(exampleProjectPath);
|
|
}, timeout: allowForRemotePubInvocation);
|
|
});
|
|
|
|
group('packages test/pub', () {
|
|
MockProcessManager mockProcessManager;
|
|
MockStdio mockStdio;
|
|
|
|
setUp(() {
|
|
mockProcessManager = new MockProcessManager();
|
|
mockStdio = new MockStdio();
|
|
});
|
|
|
|
testUsingContext('test without bot', () async {
|
|
await createTestCommandRunner(new PackagesCommand()).run(<String>['packages', 'test']);
|
|
final List<String> commands = mockProcessManager.commands;
|
|
expect(commands, hasLength(3));
|
|
expect(commands[0], matches(r'dart-sdk[\\/]bin[\\/]pub'));
|
|
expect(commands[1], 'run');
|
|
expect(commands[2], 'test');
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
Stdio: () => mockStdio,
|
|
BotDetector: () => const AlwaysFalseBotDetector(),
|
|
});
|
|
|
|
testUsingContext('test with bot', () async {
|
|
await createTestCommandRunner(new PackagesCommand()).run(<String>['packages', 'test']);
|
|
final List<String> commands = mockProcessManager.commands;
|
|
expect(commands, hasLength(4));
|
|
expect(commands[0], matches(r'dart-sdk[\\/]bin[\\/]pub'));
|
|
expect(commands[1], '--trace');
|
|
expect(commands[2], 'run');
|
|
expect(commands[3], 'test');
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
Stdio: () => mockStdio,
|
|
BotDetector: () => const AlwaysTrueBotDetector(),
|
|
});
|
|
|
|
testUsingContext('run', () async {
|
|
await createTestCommandRunner(new PackagesCommand()).run(<String>['packages', '--verbose', 'pub', 'run', '--foo', 'bar']);
|
|
final List<String> commands = mockProcessManager.commands;
|
|
expect(commands, hasLength(4));
|
|
expect(commands[0], matches(r'dart-sdk[\\/]bin[\\/]pub'));
|
|
expect(commands[1], 'run');
|
|
expect(commands[2], '--foo');
|
|
expect(commands[3], 'bar');
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
Stdio: () => mockStdio,
|
|
});
|
|
|
|
testUsingContext('publish', () async {
|
|
final PromptingProcess process = new PromptingProcess();
|
|
mockProcessManager.processFactory = (List<String> commands) => process;
|
|
final Future<Null> runPackages = createTestCommandRunner(new PackagesCommand()).run(<String>['packages', 'pub', 'publish']);
|
|
final Future<Null> runPrompt = process.showPrompt('Proceed (y/n)? ', <String>['hello', 'world']);
|
|
final Future<Null> simulateUserInput = new Future<Null>(() {
|
|
mockStdio.simulateStdin('y');
|
|
});
|
|
await Future.wait(<Future<Null>>[runPackages, runPrompt, simulateUserInput]);
|
|
final List<String> commands = mockProcessManager.commands;
|
|
expect(commands, hasLength(2));
|
|
expect(commands[0], matches(r'dart-sdk[\\/]bin[\\/]pub'));
|
|
expect(commands[1], 'publish');
|
|
final List<String> stdout = mockStdio.writtenToStdout;
|
|
expect(stdout, hasLength(4));
|
|
expect(stdout.sublist(0, 2), contains('Proceed (y/n)? '));
|
|
expect(stdout.sublist(0, 2), contains('y\n'));
|
|
expect(stdout[2], 'hello\n');
|
|
expect(stdout[3], 'world\n');
|
|
}, overrides: <Type, Generator>{
|
|
ProcessManager: () => mockProcessManager,
|
|
Stdio: () => mockStdio,
|
|
});
|
|
});
|
|
}
|