Run "pub global activate devtools" before overall_experience_test (#85812)

This commit is contained in:
Ian Hickson 2021-07-12 14:36:05 -07:00 committed by GitHub
parent 3eca034ffd
commit d3c17acf9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 131 additions and 69 deletions

View File

@ -1,18 +1,31 @@
## Flutter SDK dependency versions
The files in this directory specifies pinned versions of various dependencies of the flutter SDK.
The files in this directory specifies pinned versions of various
dependencies of the flutter SDK.
The `bin/internal/engine.version` file controls which version of the Flutter engine to use.
The file contains the commit hash of a commit in the <https://github.com/flutter/engine> repository.
That hash must have successfully been compiled on <https://build.chromium.org/p/client.flutter/> and had its artifacts (the binaries that run on Android and iOS, the compiler, etc) successfully uploaded to Google Cloud Storage.
The `bin/internal/engine.version` file controls which version of the
Flutter engine to use. The file contains the commit hash of a commit
in the <https://github.com/flutter/engine> repository. That hash must
have successfully been compiled on
<https://build.chromium.org/p/client.flutter/> and had its artifacts
(the binaries that run on Android and iOS, the compiler, etc)
successfully uploaded to Google Cloud Storage.
The `/bin/internal/engine.merge_method` file controls how we merge a pull
request created by the engine auto-roller. If it's `squash`, there's only one
commit for a pull request no matter how many engine commits there are inside
that pull request. If it's `rebase`, the number of commits in the framework is
equal to the number of engine commits in the pull request. The latter method
makes it easier to detect regressions but costs more test resources.
The `/bin/internal/engine.merge_method` file controls how we merge a
pull request created by the engine auto-roller. If it's `squash`,
there's only one commit for a pull request no matter how many engine
commits there are inside that pull request. If it's `rebase`, the
number of commits in the framework is equal to the number of engine
commits in the pull request. The latter method makes it easier to
detect regressions but costs more test resources.
Ths `bin/internal/flutter_plugins.version` file specifies the version of the `flutter/plugins` repository to be used for testing.
Note that `flutter/plugins` isn't an upstream dependency of `flutter/flutter` it is only used as part of the test suite for verification,
the pinned version here makes sure that tests are deterministic at each `flutter/flutter` commit.
Ths `bin/internal/flutter_plugins.version` file specifies the version
of the `flutter/plugins` repository to be used for testing. The
`flutter/plugins` repository isn't an upstream dependency of
`flutter/flutter`; it is only used as part of the test suite for
verification, and the pinned version here makes sure that tests are
deterministic at each `flutter/flutter` commit.
The `bin/internal/devtools.version` file specifies the version of the
`devtools` package on `pub` that should be activated when running the
Flutter command line tool.

View File

@ -0,0 +1 @@
2.4.0

View File

@ -143,11 +143,6 @@ function upgrade_flutter () (
PUB_ENVIRONMENT="$PUB_ENVIRONMENT:flutter_bot"
VERBOSITY="--verbosity=normal"
fi
# Increase verbosity for Flutter's LUCI CI infra.
if [[ -n "$LUCI_CI" ]]; then
PUB_ENVIRONMENT="$PUB_ENVIRONMENT:flutter_bot"
VERBOSITY="--verbosity=all"
fi
export PUB_ENVIRONMENT="$PUB_ENVIRONMENT:flutter_install"

View File

@ -129,7 +129,7 @@ Future<Command> startCommand(String executable, List<String> arguments, {
switch (outputMode) {
case OutputMode.print:
stdoutSource.listen(io.stdout.add);
process.stderr.listen(io.stderr.add);
process.stderr.listen(io.stdout.add);
break;
case OutputMode.capture:
savedStdout = stdoutSource.toList();
@ -190,7 +190,7 @@ Future<CommandResult> runCommand(String executable, List<String> arguments, {
break;
case OutputMode.capture:
io.stdout.writeln(result.flattenedStdout);
io.stderr.writeln(result.flattenedStderr);
io.stdout.writeln(result.flattenedStderr);
break;
}
exitWithError(<String>[
@ -213,7 +213,7 @@ String _flattenToString(List<List<int>> chunks) =>
/// Specifies what to do with the command output from [runCommand] and [startCommand].
enum OutputMode {
/// Forwards standard output and standard error streams to the test process'
/// respective standard streams.
/// standard output stream (i.e. stderr is redirected to stdout).
///
/// Use this mode if all you want is print the output of the command to the
/// console. The output is no longer available after the process exits.

View File

@ -302,6 +302,25 @@ Future<void> _runIntegrationToolTests() async {
.map<String>((FileSystemEntity entry) => path.relative(entry.path, from: toolsPath))
.where((String testPath) => path.basename(testPath).endsWith('_test.dart')).toList();
// Make sure devtools is ready first, because that might take a while and we don't
// want any of the tests to time out while they themselves try to activate devtools.
final Map<String, String> pubEnvironment = <String, String>{
'FLUTTER_ROOT': flutterRoot,
};
if (Directory(pubCache).existsSync()) {
pubEnvironment['PUB_CACHE'] = pubCache;
}
await runCommand(
pub,
<String>[
'global',
'activate',
'devtools',
File(path.join(flutterRoot, 'bin', 'internal', 'devtools.version')).readAsStringSync(),
],
environment: pubEnvironment,
);
await _pubRunTest(
toolsPath,
forceSingleCore: true,
@ -703,7 +722,7 @@ Future<void> _runFrameworkTests() async {
Future<void> runMisc() async {
print('${green}Running package tests$reset for directories other than packages/flutter');
await _pubRunTest(path.join(flutterRoot, 'dev', 'bots'));
await _pubRunTest(path.join(flutterRoot, 'dev', 'devicelab'));
await _pubRunTest(path.join(flutterRoot, 'dev', 'devicelab'), ensurePrecompiledTool: false);
await _pubRunTest(path.join(flutterRoot, 'dev', 'snippets'));
// TODO(fujino): Move this to its own test shard
await _pubRunTest(path.join(flutterRoot, 'dev', 'conductor'), forceSingleCore: true);
@ -1417,6 +1436,7 @@ Future<void> _pubRunTest(String workingDirectory, {
bool forceSingleCore = false,
Duration perTestTimeout,
bool includeLocalEngineEnv = false,
bool ensurePrecompiledTool = true,
}) async {
int cpus;
final String cpuVariable = Platform.environment['CPU']; // CPU is set in cirrus.yml
@ -1473,6 +1493,12 @@ Future<void> _pubRunTest(String workingDirectory, {
deleteFile(path.join(flutterRoot, 'bin', 'cache', 'flutter_tools.snapshot'));
deleteFile(path.join(flutterRoot, 'bin', 'cache', 'flutter_tools.stamp'));
}
if (ensurePrecompiledTool) {
// We rerun the `flutter` tool here just to make sure that it is compiled
// before tests run, because the tests might time out if they have to rebuild
// the tool themselves.
await runCommand(flutter, <String>['--version'], environment: pubEnvironment);
}
if (useFlutterTestFormatter) {
final FlutterCompactFormatter formatter = FlutterCompactFormatter();
Stream<String> testOutput;

View File

@ -109,6 +109,7 @@ Future<void> main(List<String> args) async {
// devtools source code.
DevtoolsLauncher: () => DevtoolsServerLauncher(
processManager: globals.processManager,
fileSystem: globals.fs,
pubExecutable: globals.artifacts.getHostArtifact(HostArtifact.pubExecutable).path,
logger: globals.logger,
platform: globals.platform,

View File

@ -215,6 +215,7 @@ Future<T> runInContext<T>(
),
DevtoolsLauncher: () => DevtoolsServerLauncher(
processManager: globals.processManager,
fileSystem: globals.fs,
pubExecutable: globals.artifacts.getHostArtifact(HostArtifact.pubExecutable).path,
logger: globals.logger,
platform: globals.platform,

View File

@ -9,9 +9,11 @@ import 'dart:async';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'base/file_system.dart';
import 'base/io.dart' as io;
import 'base/logger.dart';
import 'base/platform.dart';
import 'cache.dart';
import 'convert.dart';
import 'persistent_tool_state.dart';
import 'resident_runner.dart';
@ -22,11 +24,13 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
DevtoolsServerLauncher({
@required Platform platform,
@required ProcessManager processManager,
@required FileSystem fileSystem,
@required String pubExecutable,
@required Logger logger,
@required PersistentToolState persistentToolState,
@visibleForTesting io.HttpClient httpClient,
}) : _processManager = processManager,
_fileSystem = fileSystem,
_pubExecutable = pubExecutable,
_logger = logger,
_platform = platform,
@ -34,6 +38,7 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
_httpClient = httpClient ?? io.HttpClient();
final ProcessManager _processManager;
final FileSystem _fileSystem;
final String _pubExecutable;
final Logger _logger;
final Platform _platform;
@ -44,9 +49,16 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
io.Process _devToolsProcess;
static final RegExp _serveDevToolsPattern =
RegExp(r'Serving DevTools at ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)');
RegExp(r'Serving DevTools at ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+?)\.?$');
static const String _pubHostedUrlKey = 'PUB_HOSTED_URL';
static String _devtoolsVersion;
static String devtoolsVersion(FileSystem fs) {
return _devtoolsVersion ??= fs.file(
fs.path.join(Cache.flutterRoot, 'bin', 'internal', 'devtools.version'),
).readAsStringSync();
}
@override
Future<void> get processStart => _processStartCompleter.future;
@ -95,9 +107,9 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
bool devToolsActive = await _checkForActiveDevTools();
if (!offline) {
await _activateDevTools(throttleUpdates: devToolsActive);
}
if (!devToolsActive && !offline) {
devToolsActive = await _checkForActiveDevTools();
if (!devToolsActive) {
devToolsActive = await _checkForActiveDevTools();
}
}
if (!devToolsActive) {
// We don't have devtools installed and installing it failed;
@ -122,15 +134,8 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
.listen((String line) {
final Match match = _serveDevToolsPattern.firstMatch(line);
if (match != null) {
// We are trying to pull "http://127.0.0.1:9101" from "Serving
// DevTools at http://127.0.0.1:9101.". `match[1]` will return
// "http://127.0.0.1:9101.", and we need to trim the trailing period
// so that we don't throw an exception from `Uri.parse`.
String uri = match[1];
if (uri.endsWith('.')) {
uri = uri.substring(0, uri.length - 1);
}
completer.complete(Uri.parse(uri));
final String url = match[1];
completer.complete(Uri.parse(url));
}
});
_devToolsProcess.stderr
@ -178,7 +183,7 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
'global',
'activate',
'devtools',
'2.4.0',
devtoolsVersion(_fileSystem),
]);
if (_devToolsActivateProcess.exitCode != 0) {
_logger.printError(

View File

@ -6,10 +6,12 @@
import 'dart:async';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.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/cache.dart';
import 'package:flutter_tools/src/devtools_launcher.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/persistent_tool_state.dart';
@ -24,6 +26,13 @@ void main() {
FakePlatform platform;
PersistentToolState persistentToolState;
Cache.flutterRoot = '';
const String devtoolsVersion = '1.2.3';
final MemoryFileSystem fakefs = MemoryFileSystem.test()
..directory('bin').createSync()
..directory('bin/internal').createSync()
..file('bin/internal/devtools.version').writeAsStringSync(devtoolsVersion);
setUp(() {
logger = BufferLogger.test();
platform = FakePlatform(environment: <String, String>{});
@ -38,6 +47,7 @@ void main() {
testWithoutContext('DevtoolsLauncher does not launch devtools if unable to reach pub.dev and there is no activated package', () async {
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,
@ -68,6 +78,7 @@ void main() {
final Completer<void> completer = Completer<void>();
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,
@ -109,6 +120,7 @@ void main() {
testWithoutContext('DevtoolsLauncher pings PUB_HOSTED_URL instead of pub.dev for online check', () async {
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: FakePlatform(environment: <String, String>{
'PUB_HOSTED_URL': 'https://pub2.dev'
@ -140,6 +152,7 @@ void main() {
testWithoutContext('DevtoolsLauncher handles an invalid PUB_HOSTED_URL', () async {
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: FakePlatform(environment: <String, String>{
'PUB_HOSTED_URL': r'not_an_http_url'
@ -167,6 +180,7 @@ void main() {
final Completer<void> completer = Completer<void>();
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,
@ -178,7 +192,7 @@ void main() {
'global',
'list',
],
stdout: 'devtools 2.4.0',
stdout: 'devtools $devtoolsVersion',
),
const FakeCommand(
command: <String>[
@ -186,9 +200,9 @@ void main() {
'global',
'activate',
'devtools',
'2.4.0',
devtoolsVersion,
],
stdout: 'Activated DevTools 2.4.0',
stdout: 'Activated DevTools $devtoolsVersion',
),
FakeCommand(
command: const <String>[
@ -213,6 +227,7 @@ void main() {
final Completer<void> completer = Completer<void>();
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,
@ -232,9 +247,9 @@ void main() {
'global',
'activate',
'devtools',
'2.4.0'
devtoolsVersion,
],
stdout: 'Activated DevTools 2.4.0',
stdout: 'Activated DevTools $devtoolsVersion',
),
const FakeCommand(
command: <String>[
@ -242,7 +257,7 @@ void main() {
'global',
'list',
],
stdout: 'devtools 2.4.0',
stdout: 'devtools $devtoolsVersion',
),
FakeCommand(
command: const <String>[
@ -267,6 +282,7 @@ void main() {
final Completer<void> completer = Completer<void>();
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,
@ -278,7 +294,7 @@ void main() {
'global',
'list',
],
stdout: 'devtools 2.4.0',
stdout: 'devtools $devtoolsVersion',
),
const FakeCommand(
command: <String>[
@ -286,9 +302,9 @@ void main() {
'global',
'activate',
'devtools',
'2.4.0'
devtoolsVersion,
],
stdout: 'Activated DevTools 2.4.0',
stdout: 'Activated DevTools $devtoolsVersion',
),
FakeCommand(
command: const <String>[
@ -318,6 +334,7 @@ void main() {
persistentToolState.lastDevToolsActivation = DateTime.now();
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,
@ -329,7 +346,7 @@ void main() {
'global',
'list',
],
stdout: 'devtools 2.4.0',
stdout: 'devtools $devtoolsVersion',
),
const FakeCommand(
command: <String>[
@ -356,7 +373,7 @@ void main() {
'global',
'list',
],
stdout: 'devtools 2.4.0',
stdout: 'devtools $devtoolsVersion',
),
const FakeCommand(
command: <String>[
@ -373,6 +390,7 @@ void main() {
]);
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,
@ -389,6 +407,7 @@ void main() {
testWithoutContext('DevtoolsLauncher prints error if exception is thrown during activate', () async {
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,
@ -400,7 +419,7 @@ void main() {
'global',
'list',
],
stdout: 'devtools 2.4.0',
stdout: 'devtools $devtoolsVersion',
),
const FakeCommand(
command: <String>[
@ -408,7 +427,7 @@ void main() {
'global',
'activate',
'devtools',
'2.4.0',
devtoolsVersion,
],
stderr: 'Error - could not activate devtools',
exitCode: 1,
@ -435,6 +454,7 @@ void main() {
testWithoutContext('DevtoolsLauncher prints error if exception is thrown during launch', () async {
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,
@ -446,7 +466,7 @@ void main() {
'global',
'list',
],
stdout: 'devtools 2.4.0',
stdout: 'devtools $devtoolsVersion',
),
const FakeCommand(
command: <String>[
@ -454,9 +474,9 @@ void main() {
'global',
'activate',
'devtools',
'2.4.0'
devtoolsVersion,
],
stdout: 'Activated DevTools 2.4.0',
stdout: 'Activated DevTools $devtoolsVersion',
),
const FakeCommand(
command: <String>[
@ -480,6 +500,7 @@ void main() {
testWithoutContext('DevtoolsLauncher prints trace if connecting to pub.dev throws', () async {
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,
@ -510,6 +531,7 @@ void main() {
testWithoutContext('DevtoolsLauncher prints trace if connecting to pub.dev returns non-OK status code', () async {
final DevtoolsLauncher launcher = DevtoolsServerLauncher(
pubExecutable: 'pub',
fileSystem: fakefs,
logger: logger,
platform: platform,
persistentToolState: persistentToolState,

View File

@ -6,9 +6,11 @@
import 'dart:async';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/devtools_launcher.dart';
import 'package:flutter_tools/src/resident_devtools_handler.dart';
@ -75,6 +77,12 @@ final FakeVmServiceRequest listViews = FakeVmServiceRequest(
);
void main() {
Cache.flutterRoot = '';
final MemoryFileSystem fakefs = MemoryFileSystem.test()
..directory('bin').createSync()
..directory('bin/internal').createSync()
..file('bin/internal/devtools.version').writeAsStringSync('1.0.0');
testWithoutContext('Does not serve devtools if launcher is null', () async {
final ResidentDevtoolsHandler handler = FlutterResidentDevtoolsHandler(
null,
@ -102,6 +110,7 @@ void main() {
testWithoutContext('Can use devtools with existing devtools URI', () async {
final DevtoolsServerLauncher launcher = DevtoolsServerLauncher(
processManager: FakeProcessManager.empty(),
fileSystem: fakefs,
pubExecutable: 'pub',
logger: BufferLogger.test(),
platform: FakePlatform(),

View File

@ -442,21 +442,10 @@ void main() {
} finally {
tryToDelete(fileSystem.directory(tempDirectory));
}
}, skip: Platform.isWindows); // TODO(jonahwilliams): Re-enable when this test is reliable on device lab, https://github.com/flutter/flutter/issues/81556
});
testWithoutContext('flutter error messages include a DevTools link', () async {
final String testDirectory = fileSystem.path.join(flutterRoot, 'dev', 'integration_tests', 'ui');
// Ensure that DevTools is activated.
final ProcessResult pubResult = await processManager.run(<String>[
fileSystem.path.join(flutterRoot, 'bin', 'cache', 'dart-sdk', 'bin', 'dart'),
'pub', 'global', 'activate', 'devtools', '2.4.0',
], workingDirectory: testDirectory).timeout(const Duration(seconds: 20));
if (pubResult.exitCode != 0) {
print('Unable to activate devtools:\n${pubResult.stderr}');
}
expect(pubResult.exitCode, 0);
final String tempDirectory = fileSystem.systemTempDirectory.createTempSync('flutter_overall_experience_test.').resolveSymbolicLinksSync();
final String testScript = fileSystem.path.join('lib', 'overflow.dart');
try {
@ -520,16 +509,16 @@ void main() {
} finally {
tryToDelete(fileSystem.directory(tempDirectory));
}
}, skip: Platform.isWindows); // TODO(goderbauer): Re-enable when this test is reliable on device lab, https://github.com/flutter/flutter/issues/81486
});
testWithoutContext('flutter run help output', () async {
// This test enables all logging so that it checks the exact text of starting up an application.
// The idea is to verify that we're not outputting spurious messages.
// WHEN EDITING THIS TEST PLEASE CAREFULLY CONSIDER WHETHER THE NEW OUTPUT IS AN IMPROVEMENT.
final String testDirectory = fileSystem.path.join(flutterRoot, 'examples', 'hello_world');
final RegExp finalLine = RegExp(r'^An Observatory'); /* RegExp(r'^The Flutter DevTools'); */ // TODO(ianh): use this when enabling devtools
final RegExp finalLine = RegExp(r'^The Flutter DevTools');
final ProcessTestResult result = await runFlutter(
<String>['run', '-dflutter-tester', '--no-devtools'], // TODO(ianh): enable devtools
<String>['run', '-dflutter-tester'],
testDirectory,
<Transition>[
Barrier(finalLine, handler: (String line) {
@ -558,7 +547,7 @@ void main() {
contains('Running with sound null safety'),
'',
startsWith('An Observatory debugger and profiler on Flutter test device is available at: http://'),
/* startsWith('The Flutter DevTools debugger and profiler on Flutter test device is available at: http://'), */ // TODO(ianh): enable devtools
startsWith('The Flutter DevTools debugger and profiler on Flutter test device is available at: http://'),
'',
'Flutter run key commands.',
startsWith('r Hot reload.'),
@ -587,7 +576,7 @@ void main() {
contains('Running with sound null safety'),
'',
startsWith('An Observatory debugger and profiler on Flutter test device is available at: http://'),
/* startsWith('The Flutter DevTools debugger and profiler on Flutter test device is available at: http://'), */ // TODO(ianh): enable devtools
startsWith('The Flutter DevTools debugger and profiler on Flutter test device is available at: http://'),
'',
'Application finished.',
]);