This reverts commit 1781d5c9bbb4a1b408e40bd40e433c3541bb68fc.
This commit is contained in:
parent
be7937965c
commit
1982a5c3ec
1139
.cirrus.yml
1139
.cirrus.yml
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,3 @@ This directory contains tools and resources that the Flutter team uses
|
||||
during development of the framework. The tools in this directory
|
||||
should not be necessary for developing Flutter applications, though of
|
||||
course they may be interesting if you are curious.
|
||||
|
||||
The tests in this directory are run in the `framework_tests_misc-*`
|
||||
shards.
|
||||
|
@ -1,19 +1,31 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# This script is only meant to be run by the Cirrus CI system, not locally.
|
||||
# It must be run from the root of the Flutter repo.
|
||||
|
||||
function error() {
|
||||
echo "$@" 1>&2
|
||||
}
|
||||
|
||||
# This script is only meant to be run by the Cirrus CI system, not locally.
|
||||
# It must be run from the root of the Flutter repo.
|
||||
|
||||
function accept_android_licenses() {
|
||||
yes "y" | flutter doctor --android-licenses > /dev/null 2>&1
|
||||
}
|
||||
|
||||
echo "Flutter SDK directory is: $PWD"
|
||||
|
||||
# Run flutter to download dependencies and precompile things, and to disable
|
||||
# analytics on the bots.
|
||||
echo "Downloading build dependencies and pre-compiling Flutter snapshot"
|
||||
./bin/flutter config --no-analytics
|
||||
|
||||
# Run doctor, to print it to the log for debugging purposes.
|
||||
./bin/flutter doctor -v
|
||||
|
||||
# Accept licenses.
|
||||
echo "Accepting Android licenses."
|
||||
accept_android_licenses || (error "Accepting Android licenses failed." && false)
|
||||
|
||||
# Run pub get in all the repo packages.
|
||||
echo "Updating packages for Flutter."
|
||||
./bin/flutter update-packages
|
@ -24,9 +24,11 @@ set -x
|
||||
|
||||
cd "$FLUTTER_ROOT"
|
||||
|
||||
if [[ "$SHARD" = "deploy_gallery" ]]; then
|
||||
version="$(<version)"
|
||||
if [[ "$OS" == "linux" ]]; then
|
||||
echo "Building Flutter Gallery $version for Android..."
|
||||
|
||||
# ANDROID_SDK_ROOT must be set in the env.
|
||||
(
|
||||
cd examples/flutter_gallery
|
||||
@ -45,7 +47,7 @@ if [[ "$OS" == "linux" ]]; then
|
||||
fastlane deploy_play_store
|
||||
)
|
||||
else
|
||||
echo "(Not deploying; Flutter Gallery is only deployed to Play store for tagged dev branch commits.)"
|
||||
echo "Not deployed: Flutter Gallery is only deployed to the Play Store on merged and tagged dev branch commits"
|
||||
fi
|
||||
elif [[ "$OS" == "darwin" ]]; then
|
||||
echo "Building Flutter Gallery $version for iOS..."
|
||||
@ -93,21 +95,17 @@ elif [[ "$OS" == "darwin" ]]; then
|
||||
fastlane build_and_deploy_testflight upload:true
|
||||
)
|
||||
else
|
||||
# On iOS the signing can break as well, so we verify this regularly (not just
|
||||
# on tagged dev branch commits). We can only do this post-merge, though, because
|
||||
# the secrets aren't available on PRs.
|
||||
echo "Testing archiving with distribution profile..."
|
||||
echo "Archiving with distribution profile..."
|
||||
(
|
||||
cd examples/flutter_gallery/ios
|
||||
fastlane build_and_deploy_testflight
|
||||
)
|
||||
echo "(Not deploying; Flutter Gallery is only deployed to TestFlight for tagged dev branch commits.)"
|
||||
echo "Archive is only deployed to TestFlight on tagged dev branch commits"
|
||||
fi
|
||||
else
|
||||
echo "(Not archiving or deploying; Flutter Gallery archiving is only tested post-commit.)"
|
||||
echo "Not deployed: Flutter Gallery is only deployed to TestFlight on merged and tagged dev branch commits"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Unknown OS: $OS"
|
||||
echo "Aborted."
|
||||
exit 1
|
||||
echo "Doing nothing: not on the 'deploy_gallery' SHARD."
|
||||
fi
|
||||
|
@ -95,6 +95,7 @@ Future<void> runCommand(String executable, List<String> arguments, {
|
||||
OutputMode outputMode = OutputMode.print,
|
||||
CapturedOutput output,
|
||||
bool skip = false,
|
||||
bool expectFlaky = false,
|
||||
bool Function(String) removeLine,
|
||||
}) async {
|
||||
assert((outputMode == OutputMode.capture) == (output != null),
|
||||
@ -144,6 +145,10 @@ Future<void> runCommand(String executable, List<String> arguments, {
|
||||
output.stderr = _flattenToString(await savedStderr);
|
||||
}
|
||||
|
||||
// If the test is flaky we don't care about the actual exit.
|
||||
if (expectFlaky)
|
||||
return;
|
||||
|
||||
if ((exitCode == 0) == expectNonZeroExit || (expectedExitCode != null && exitCode != expectedExitCode)) {
|
||||
if (failureMessage != null) {
|
||||
print(failureMessage);
|
||||
|
1079
dev/bots/test.dart
1079
dev/bots/test.dart
File diff suppressed because it is too large
Load Diff
@ -1,13 +0,0 @@
|
||||
// Copyright 2017 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:io';
|
||||
|
||||
import 'common.dart';
|
||||
|
||||
void main() {
|
||||
test('BOT variable is set on bots', () {
|
||||
expect(Platform.environment['BOT'], 'true');
|
||||
});
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
// Copyright 2017 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:io';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import 'common.dart';
|
||||
|
||||
void main() {
|
||||
test('We are in a directory with a space in it', () async {
|
||||
// The Flutter SDK should be in a directory with a space in it, to make sure
|
||||
// our tools support that.
|
||||
final String expectedName = Platform.environment['FLUTTER_SDK_PATH_WITH_SPACE'];
|
||||
expect(expectedName, 'flutter sdk');
|
||||
expect(expectedName, contains(' '));
|
||||
final List<String> parts = path.split(Directory.current.absolute.path);
|
||||
expect(parts.reversed.take(3), <String>['bots', 'dev', expectedName]);
|
||||
});
|
||||
}
|
@ -29,11 +29,7 @@ void main() {
|
||||
];
|
||||
for (String version in valid_versions) {
|
||||
when(file.readAsString()).thenAnswer((Invocation invocation) => Future<String>.value(version));
|
||||
expect(
|
||||
await verifyVersion(file),
|
||||
isNull,
|
||||
reason: '$version is valid but verifyVersionFile said it was bad',
|
||||
);
|
||||
expect(await verifyVersion(version, file), isTrue, reason: '$version is invalid');
|
||||
}
|
||||
});
|
||||
|
||||
@ -45,15 +41,10 @@ void main() {
|
||||
'1.2.3-pre',
|
||||
'1.2.3-pre.1+hotfix.1',
|
||||
' 1.2.3',
|
||||
'1.2.3-hotfix.1',
|
||||
];
|
||||
for (String version in invalid_versions) {
|
||||
when(file.readAsString()).thenAnswer((Invocation invocation) => Future<String>.value(version));
|
||||
expect(
|
||||
await verifyVersion(file),
|
||||
'The version logic generated an invalid version string: "$version".',
|
||||
reason: '$version is invalid but verifyVersionFile said it was fine',
|
||||
);
|
||||
expect(await verifyVersion(version, file), isFalse);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,5 @@
|
||||
# package:test configuration
|
||||
# https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md
|
||||
tags:
|
||||
"no_coverage":
|
||||
"create":
|
||||
"integration":
|
||||
|
||||
# Some of our tests take an absurdly long time to run, and on some
|
||||
# hosts they can take even longer due to the host suddenly being
|
||||
# overloaded. For this reason, we set the test timeout to
|
||||
# significantly more than it would be by default, and we never set the
|
||||
# timeouts in the tests themselves.
|
||||
timeout: 15m
|
||||
|
@ -135,7 +135,7 @@ void main() {
|
||||
return _updateIdeConfig(
|
||||
expectedContents: expectedContents,
|
||||
);
|
||||
});
|
||||
}, timeout: const Timeout.factor(2.0));
|
||||
|
||||
testUsingContext('creates non-existent files', () async {
|
||||
final Map<String, String> templateManifest = _getManifest(
|
||||
@ -155,7 +155,7 @@ void main() {
|
||||
return _updateIdeConfig(
|
||||
expectedContents: expectedContents,
|
||||
);
|
||||
});
|
||||
}, timeout: const Timeout.factor(2.0));
|
||||
|
||||
testUsingContext('overwrites existing files with --overwrite', () async {
|
||||
final Map<String, String> templateManifest = _getManifest(
|
||||
@ -181,7 +181,7 @@ void main() {
|
||||
args: <String>['--overwrite'],
|
||||
expectedContents: expectedContents,
|
||||
);
|
||||
});
|
||||
}, timeout: const Timeout.factor(2.0));
|
||||
|
||||
testUsingContext('only adds new templates without --overwrite', () async {
|
||||
final Map<String, String> templateManifest = _getManifest(
|
||||
@ -212,7 +212,7 @@ void main() {
|
||||
args: <String>['--update-templates'],
|
||||
expectedContents: expectedContents,
|
||||
);
|
||||
});
|
||||
}, timeout: const Timeout.factor(2.0));
|
||||
|
||||
testUsingContext('update all templates with --overwrite', () async {
|
||||
final Map<String, String> templateManifest = _getManifest(
|
||||
@ -239,7 +239,7 @@ void main() {
|
||||
args: <String>['--update-templates', '--overwrite'],
|
||||
expectedContents: expectedContents,
|
||||
);
|
||||
});
|
||||
}, timeout: const Timeout.factor(2.0));
|
||||
|
||||
testUsingContext('removes deleted imls with --overwrite', () async {
|
||||
final Map<String, String> templateManifest = _getManifest(
|
||||
@ -275,7 +275,7 @@ void main() {
|
||||
args: <String>['--update-templates', '--overwrite'],
|
||||
expectedContents: expectedContents,
|
||||
);
|
||||
});
|
||||
}, timeout: const Timeout.factor(2.0));
|
||||
|
||||
testUsingContext('removes deleted imls with --overwrite, including empty parent dirs', () async {
|
||||
final Map<String, String> templateManifest = _getManifest(
|
||||
@ -316,7 +316,7 @@ void main() {
|
||||
args: <String>['--update-templates', '--overwrite'],
|
||||
expectedContents: expectedContents,
|
||||
);
|
||||
});
|
||||
}, timeout: const Timeout.factor(2.0));
|
||||
|
||||
});
|
||||
}
|
||||
|
@ -16,6 +16,9 @@ import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
|
||||
/// Test case timeout for tests involving project analysis.
|
||||
const Timeout allowForSlowAnalyzeTests = Timeout.factor(5.0);
|
||||
|
||||
final Generator _kNoColorTerminalPlatform = () => FakePlatform.fromPlatform(const LocalPlatform())..stdoutSupportsAnsi = false;
|
||||
final Map<Type, Generator> noColorTerminalOverride = <Type, Generator>{
|
||||
Platform: _kNoColorTerminalPlatform,
|
||||
@ -51,7 +54,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
expect(libMain.existsSync(), isTrue);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -62,7 +65,7 @@ void main() {
|
||||
arguments: <String>['analyze'],
|
||||
statusTextContains: <String>['No issues found!'],
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForSlowAnalyzeTests, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -77,7 +80,6 @@ void main() {
|
||||
}, 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
|
||||
@ -108,7 +110,7 @@ void main() {
|
||||
exitMessageContains: '2 issues found.',
|
||||
toolExit: true,
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForSlowAnalyzeTests, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
...noColorTerminalOverride,
|
||||
});
|
||||
@ -138,7 +140,7 @@ void main() {
|
||||
exitMessageContains: '3 issues found.',
|
||||
toolExit: true,
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForSlowAnalyzeTests, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
...noColorTerminalOverride
|
||||
});
|
||||
|
@ -73,7 +73,7 @@ void main() {
|
||||
|
||||
expect(await command.usageValues,
|
||||
containsPair(CustomDimensions.commandBuildBundleIsModule, 'true'));
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('bundle getUsage indicate that project is not a module', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -83,7 +83,7 @@ void main() {
|
||||
|
||||
expect(await command.usageValues,
|
||||
containsPair(CustomDimensions.commandBuildBundleIsModule, 'false'));
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('bundle getUsage indicate the target platform', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -93,7 +93,7 @@ void main() {
|
||||
|
||||
expect(await command.usageValues,
|
||||
containsPair(CustomDimensions.commandBuildBundleTargetPlatform, 'android-arm'));
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('bundle fails to build for Windows if feature is disabled', () async {
|
||||
fs.file('lib/main.dart').createSync(recursive: true);
|
||||
|
@ -78,7 +78,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
return _runFlutterTest(projectDir);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -96,7 +96,7 @@ void main() {
|
||||
'ios/Runner/GeneratedPluginRegistrant.h',
|
||||
],
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -118,9 +118,11 @@ void main() {
|
||||
'ios/',
|
||||
]);
|
||||
return _runFlutterTest(projectDir);
|
||||
}, overrides: <Type, Generator>{
|
||||
},
|
||||
timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext('cannot create a project if non-empty non-project directory exists with .metadata', () async {
|
||||
await projectDir.absolute.childDirectory('blag').create(recursive: true);
|
||||
@ -136,7 +138,7 @@ void main() {
|
||||
'.ios/',
|
||||
]),
|
||||
throwsToolExit(message: 'Sorry, unable to detect the type of project to recreate'));
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
...noColorTerminalOverride,
|
||||
});
|
||||
@ -162,7 +164,7 @@ void main() {
|
||||
'.ios/',
|
||||
],
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -187,7 +189,7 @@ void main() {
|
||||
'.ios/',
|
||||
],
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -212,7 +214,7 @@ void main() {
|
||||
'lib/flutter_project.dart',
|
||||
],
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -243,7 +245,7 @@ void main() {
|
||||
'test/widget_test.dart',
|
||||
],
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -265,7 +267,7 @@ void main() {
|
||||
'ios/Runner/main.m',
|
||||
],
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -295,7 +297,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
return _runFlutterTest(projectDir);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -317,7 +319,7 @@ void main() {
|
||||
],
|
||||
);
|
||||
return _runFlutterTest(projectDir.childDirectory('example'));
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -344,7 +346,7 @@ void main() {
|
||||
'example/ios/Runner/main.m',
|
||||
],
|
||||
);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('plugin project with custom org', () async {
|
||||
return _createProject(
|
||||
@ -364,7 +366,7 @@ void main() {
|
||||
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
|
||||
],
|
||||
);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('plugin project with valid custom project name', () async {
|
||||
return _createProject(
|
||||
@ -384,7 +386,7 @@ void main() {
|
||||
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
|
||||
],
|
||||
);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('plugin project with invalid custom project name', () async {
|
||||
expect(
|
||||
@ -394,7 +396,7 @@ void main() {
|
||||
),
|
||||
throwsToolExit(message: '"xyz.xyz" is not a valid Dart package name.'),
|
||||
);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('legacy app project with-driver-test', () async {
|
||||
return _createAndAnalyzeProject(
|
||||
@ -402,7 +404,7 @@ void main() {
|
||||
<String>['--with-driver-test', '--template=app'],
|
||||
<String>['lib/main.dart'],
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -437,7 +439,7 @@ void main() {
|
||||
'android/',
|
||||
'ios/',
|
||||
]);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -461,7 +463,7 @@ void main() {
|
||||
final String actualContents = await fs.file(projectDir.path + '/android/gradle.properties').readAsString();
|
||||
|
||||
expect(actualContents.contains('useAndroidX'), true);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('non androidx app project', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -482,7 +484,7 @@ void main() {
|
||||
final String actualContents = await fs.file(projectDir.path + '/android/gradle.properties').readAsString();
|
||||
|
||||
expect(actualContents.contains('useAndroidX'), false);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('androidx is used by default in a module project', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -499,7 +501,7 @@ void main() {
|
||||
project.usesAndroidX,
|
||||
true,
|
||||
);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('non androidx module', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -516,7 +518,7 @@ void main() {
|
||||
project.usesAndroidX,
|
||||
false,
|
||||
);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('androidx is used by default in a plugin project', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -537,7 +539,7 @@ void main() {
|
||||
final String actualContents = await fs.file(projectDir.path + '/android/gradle.properties').readAsString();
|
||||
|
||||
expect(actualContents.contains('useAndroidX'), true);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('non androidx plugin project', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -558,7 +560,7 @@ void main() {
|
||||
final String actualContents = await fs.file(projectDir.path + '/android/gradle.properties').readAsString();
|
||||
|
||||
expect(actualContents.contains('useAndroidX'), false);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('app supports macOS if requested', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -571,7 +573,7 @@ void main() {
|
||||
await runner.run(<String>['create', '--no-pub', '--macos', projectDir.path]);
|
||||
|
||||
expect(projectDir.childDirectory('macos').childDirectory('Runner.xcworkspace').existsSync(), true);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('app does not include macOS by default', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -584,7 +586,7 @@ void main() {
|
||||
await runner.run(<String>['create', '--no-pub', projectDir.path]);
|
||||
|
||||
expect(projectDir.childDirectory('macos').childDirectory('Runner.xcworkspace').existsSync(), false);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('plugin supports macOS if requested', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -597,7 +599,7 @@ void main() {
|
||||
await runner.run(<String>['create', '--no-pub', '--template=plugin', '--macos', projectDir.path]);
|
||||
|
||||
expect(projectDir.childDirectory('macos').childFile('flutter_project.podspec').existsSync(), true);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('plugin does not include macOS by default', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -610,7 +612,7 @@ void main() {
|
||||
await runner.run(<String>['create', '--no-pub', '--template=plugin', projectDir.path]);
|
||||
|
||||
expect(projectDir.childDirectory('macos').childFile('flutter_project.podspec').existsSync(), false);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('has correct content and formatting with module template', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -706,7 +708,7 @@ void main() {
|
||||
}, overrides: <Type, Generator>{
|
||||
FlutterVersion: () => mockFlutterVersion,
|
||||
Platform: _kNoColorTerminalPlatform,
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('has correct content and formatting with app template', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -777,7 +779,7 @@ void main() {
|
||||
}, overrides: <Type, Generator>{
|
||||
FlutterVersion: () => mockFlutterVersion,
|
||||
Platform: _kNoColorTerminalPlatform,
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('has correct application id for android and bundle id for ios', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -825,7 +827,7 @@ void main() {
|
||||
}, overrides: <Type, Generator>{
|
||||
FlutterVersion: () => mockFlutterVersion,
|
||||
Platform: _kNoColorTerminalPlatform,
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('can re-gen default template over existing project', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -839,7 +841,7 @@ void main() {
|
||||
|
||||
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
|
||||
expect(metadata, contains('project_type: app\n'));
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('can re-gen default template over existing app project with no metadta and detect the type', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -856,7 +858,7 @@ void main() {
|
||||
|
||||
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
|
||||
expect(metadata, contains('project_type: app\n'));
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('can re-gen app template over existing app project and detect the type', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -870,7 +872,7 @@ void main() {
|
||||
|
||||
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
|
||||
expect(metadata, contains('project_type: app\n'));
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('can re-gen template over existing module project and detect the type', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -884,7 +886,7 @@ void main() {
|
||||
|
||||
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
|
||||
expect(metadata, contains('project_type: module\n'));
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('can re-gen default template over existing plugin project and detect the type', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -898,7 +900,7 @@ void main() {
|
||||
|
||||
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
|
||||
expect(metadata, contains('project_type: plugin'));
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('can re-gen default template over existing package project and detect the type', () async {
|
||||
Cache.flutterRoot = '../..';
|
||||
@ -912,7 +914,7 @@ void main() {
|
||||
|
||||
final String metadata = fs.file(fs.path.join(projectDir.path, '.metadata')).readAsStringSync();
|
||||
expect(metadata, contains('project_type: package'));
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('can re-gen module .android/ folder, reusing custom org', () async {
|
||||
await _createProject(
|
||||
@ -928,7 +930,7 @@ void main() {
|
||||
'.android/app/src/main/java/com/bar/foo/flutter_project/host/MainActivity.java',
|
||||
],
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -945,7 +947,7 @@ void main() {
|
||||
await project.ios.productBundleIdentifier,
|
||||
'com.bar.foo.flutterProject',
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -972,7 +974,7 @@ void main() {
|
||||
'android/app/src/main/java/com/example/flutter_project/MainActivity.java',
|
||||
],
|
||||
);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('can re-gen app ios/ folder, reusing custom org', () async {
|
||||
await _createProject(
|
||||
@ -987,7 +989,7 @@ void main() {
|
||||
await project.ios.productBundleIdentifier,
|
||||
'com.bar.foo.flutterProject',
|
||||
);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('can re-gen plugin ios/ and example/ folders, reusing custom org', () async {
|
||||
await _createProject(
|
||||
@ -1020,7 +1022,7 @@ void main() {
|
||||
await project.example.ios.productBundleIdentifier,
|
||||
'com.bar.foo.flutterProjectExample',
|
||||
);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('fails to re-gen without specified org when org is ambiguous', () async {
|
||||
await _createProject(
|
||||
@ -1038,7 +1040,7 @@ void main() {
|
||||
() => _createProject(projectDir, <String>[], <String>[]),
|
||||
throwsToolExit(message: 'Ambiguous organization'),
|
||||
);
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
// Verify that we help the user correct an option ordering issue
|
||||
testUsingContext('produces sensible error message', () async {
|
||||
@ -1100,7 +1102,7 @@ void main() {
|
||||
'ios/Runner/GeneratedPluginRegistrant.h',
|
||||
],
|
||||
);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -1126,6 +1128,7 @@ void main() {
|
||||
expect(loggingProcessManager.commands.first, contains(matches(r'dart-sdk[\\/]bin[\\/]pub')));
|
||||
expect(loggingProcessManager.commands.first, contains('--offline'));
|
||||
},
|
||||
timeout: allowForCreateFlutterProject,
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => loggingProcessManager,
|
||||
Pub: () => const Pub(),
|
||||
@ -1144,6 +1147,7 @@ void main() {
|
||||
expect(loggingProcessManager.commands.first, contains(matches(r'dart-sdk[\\/]bin[\\/]pub')));
|
||||
expect(loggingProcessManager.commands.first, isNot(contains('--offline')));
|
||||
},
|
||||
timeout: allowForCreateFlutterProject,
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => loggingProcessManager,
|
||||
Pub: () => const Pub(),
|
||||
@ -1164,7 +1168,7 @@ void main() {
|
||||
);
|
||||
expect(projectDir.childDirectory('lib').childFile('main.dart').readAsStringSync(),
|
||||
contains('void main() {}'));
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
HttpClientFactory: () => () => MockHttpClient(200, result: 'void main() {}'),
|
||||
});
|
||||
|
||||
|
@ -207,7 +207,7 @@ void main() {
|
||||
|
||||
expectDependenciesResolved(projectPath);
|
||||
expectZeroPluginsInjected(projectPath);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -220,7 +220,7 @@ void main() {
|
||||
|
||||
expectDependenciesResolved(projectPath);
|
||||
expectZeroPluginsInjected(projectPath);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -234,7 +234,7 @@ void main() {
|
||||
|
||||
expect(await getCommand.usageValues,
|
||||
containsPair(CustomDimensions.commandPackagesNumberPlugins, '0'));
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -248,7 +248,7 @@ void main() {
|
||||
|
||||
expect(await getCommand.usageValues,
|
||||
containsPair(CustomDimensions.commandPackagesProjectModule, 'false'));
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -262,7 +262,7 @@ void main() {
|
||||
|
||||
expect(await getCommand.usageValues,
|
||||
containsPair(CustomDimensions.commandPackagesProjectModule, 'true'));
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForCreateFlutterProject, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -275,7 +275,7 @@ void main() {
|
||||
|
||||
expectDependenciesResolved(projectPath);
|
||||
expectZeroPluginsInjected(projectPath);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -288,7 +288,7 @@ void main() {
|
||||
|
||||
expectDependenciesResolved(projectPath);
|
||||
expectModulePluginInjected(projectPath);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
|
||||
@ -309,7 +309,7 @@ void main() {
|
||||
|
||||
expectDependenciesResolved(exampleProjectPath);
|
||||
expectPluginInjected(exampleProjectPath);
|
||||
}, overrides: <Type, Generator>{
|
||||
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
|
||||
Pub: () => const Pub(),
|
||||
});
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ void main() {
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
AndroidBuilder: () => FakeAndroidBuilder(),
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('indicate that project is a plugin', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -69,7 +69,7 @@ void main() {
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
AndroidBuilder: () => FakeAndroidBuilder(),
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('indicate the target platform', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -82,7 +82,7 @@ void main() {
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
AndroidBuilder: () => FakeAndroidBuilder(),
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
});
|
||||
|
||||
group('Gradle', () {
|
||||
|
@ -48,7 +48,7 @@ void main() {
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
AndroidBuilder: () => FakeAndroidBuilder(),
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('split per abi', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -65,7 +65,7 @@ void main() {
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
AndroidBuilder: () => FakeAndroidBuilder(),
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('build type', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -92,7 +92,7 @@ void main() {
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
AndroidBuilder: () => FakeAndroidBuilder(),
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
});
|
||||
|
||||
group('Gradle', () {
|
||||
@ -223,7 +223,8 @@ flutter:
|
||||
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
|
||||
GradleUtils: () => GradleUtils(),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
});
|
||||
},
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('shrinking is disabled when --no-shrink is passed', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -254,7 +255,8 @@ flutter:
|
||||
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
|
||||
GradleUtils: () => GradleUtils(),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
});
|
||||
},
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('guides the user when the shrinker fails', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -310,7 +312,8 @@ flutter:
|
||||
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Usage: () => mockUsage,
|
||||
});
|
||||
},
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('reports when the app isn\'t using AndroidX', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -363,7 +366,8 @@ flutter:
|
||||
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Usage: () => mockUsage,
|
||||
});
|
||||
},
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('reports when the app is using AndroidX', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -418,7 +422,8 @@ flutter:
|
||||
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Usage: () => mockUsage,
|
||||
});
|
||||
},
|
||||
timeout: allowForCreateFlutterProject);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ void main() {
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
AndroidBuilder: () => FakeAndroidBuilder(),
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('build type', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -75,7 +75,7 @@ void main() {
|
||||
|
||||
}, overrides: <Type, Generator>{
|
||||
AndroidBuilder: () => FakeAndroidBuilder(),
|
||||
});
|
||||
}, timeout: allowForCreateFlutterProject);
|
||||
});
|
||||
|
||||
group('Gradle', () {
|
||||
@ -212,7 +212,8 @@ flutter:
|
||||
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
|
||||
GradleUtils: () => GradleUtils(),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
});
|
||||
},
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('shrinking is disabled when --no-shrink is passed', () async {
|
||||
final String projectPath = await createProject(
|
||||
@ -245,7 +246,8 @@ flutter:
|
||||
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
|
||||
GradleUtils: () => GradleUtils(),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
});
|
||||
},
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('guides the user when the shrinker fails', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -301,7 +303,8 @@ flutter:
|
||||
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Usage: () => mockUsage,
|
||||
});
|
||||
},
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('reports when the app isn\'t using AndroidX', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -354,7 +357,8 @@ flutter:
|
||||
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Usage: () => mockUsage,
|
||||
});
|
||||
},
|
||||
timeout: allowForCreateFlutterProject);
|
||||
|
||||
testUsingContext('reports when the app is using AndroidX', () async {
|
||||
final String projectPath = await createProject(tempDir,
|
||||
@ -409,7 +413,8 @@ flutter:
|
||||
FlutterProjectFactory: () => FakeFlutterProjectFactory(tempDir),
|
||||
ProcessManager: () => mockProcessManager,
|
||||
Usage: () => mockUsage,
|
||||
});
|
||||
},
|
||||
timeout: allowForCreateFlutterProject);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,13 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Integration tests which invoke flutter instead of unit testing the code
|
||||
// will not produce meaningful coverage information - we can measure coverage
|
||||
// from the isolate running the test, but not from the isolate started via
|
||||
// the command line process.
|
||||
@Tags(<String>['no_coverage'])
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
@ -17,26 +21,49 @@ import 'test_driver.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
test('device.getDevices', () async {
|
||||
final Directory tempDir = createResolvedTempDirectorySync('daemon_mode_test.');
|
||||
|
||||
group('daemon_mode', () {
|
||||
Directory tempDir;
|
||||
final BasicProject _project = BasicProject();
|
||||
await _project.setUpIn(tempDir);
|
||||
Process process;
|
||||
|
||||
final String flutterBin = fs.path.join(getFlutterRoot(), 'bin', 'flutter');
|
||||
setUp(() async {
|
||||
tempDir = createResolvedTempDirectorySync('daemon_mode_test.');
|
||||
await _project.setUpIn(tempDir);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
tryToDelete(tempDir);
|
||||
process?.kill();
|
||||
});
|
||||
|
||||
test('device.getDevices', () async {
|
||||
final String flutterBin =
|
||||
fs.path.join(getFlutterRoot(), 'bin', 'flutter');
|
||||
|
||||
const ProcessManager processManager = LocalProcessManager();
|
||||
final Process process = await processManager.start(
|
||||
process = await processManager.start(
|
||||
<String>[flutterBin, '--show-test-device', 'daemon'],
|
||||
workingDirectory: tempDir.path,
|
||||
);
|
||||
workingDirectory: tempDir.path);
|
||||
|
||||
final StreamController<String> stdout = StreamController<String>.broadcast();
|
||||
transformToLines(process.stdout).listen((String line) => stdout.add(line));
|
||||
final Stream<Map<String, dynamic>> stream = stdout
|
||||
.stream
|
||||
.map<Map<String, dynamic>>(parseFlutterResponse)
|
||||
.where((Map<String, dynamic> value) => value != null);
|
||||
final StreamController<String> stdout =
|
||||
StreamController<String>.broadcast();
|
||||
|
||||
transformToLines(process.stdout)
|
||||
.listen((String line) => stdout.add(line));
|
||||
|
||||
final Stream<Map<String, dynamic>> stream =
|
||||
stdout.stream.where((String line) {
|
||||
final Map<String, dynamic> response = parseFlutterResponse(line);
|
||||
// ignore 'Starting device daemon...'
|
||||
if (response == null) {
|
||||
return false;
|
||||
}
|
||||
// TODO(devoncarew): Remove this after #25440 lands.
|
||||
if (response['event'] == 'daemon.showMessage') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).map(parseFlutterResponse);
|
||||
|
||||
Map<String, dynamic> response = await stream.first;
|
||||
expect(response['event'], 'daemon.connected');
|
||||
@ -67,8 +94,6 @@ void main() {
|
||||
final dynamic result = response['result'];
|
||||
expect(result, isList);
|
||||
expect(result, isNotEmpty);
|
||||
|
||||
tryToDelete(tempDir);
|
||||
process.kill();
|
||||
});
|
||||
}, timeout: const Timeout.factor(10), tags: <String>['integration']); // This test uses the `flutter` tool, which could be blocked behind the startup lock for a long time.
|
||||
}
|
||||
|
@ -2,8 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
// Integration tests which invoke flutter instead of unit testing the code
|
||||
// will not produce meaningful coverage information - we can measure coverage
|
||||
// from the isolate running the test, but not from the isolate started via
|
||||
// the command line process.
|
||||
@Tags(<String>['no_coverage'])
|
||||
import 'package:file/file.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
|
||||
@ -13,14 +16,23 @@ import 'test_driver.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
test('can step over statements', () async {
|
||||
final Directory tempDir = createResolvedTempDirectorySync('debugger_stepping_test.');
|
||||
|
||||
group('debugger', () {
|
||||
Directory tempDir;
|
||||
final SteppingProject _project = SteppingProject();
|
||||
FlutterRunTestDriver _flutter;
|
||||
|
||||
setUp(() async {
|
||||
tempDir = createResolvedTempDirectorySync('debugger_stepping_test.');
|
||||
await _project.setUpIn(tempDir);
|
||||
_flutter = FlutterRunTestDriver(tempDir);
|
||||
});
|
||||
|
||||
final FlutterRunTestDriver _flutter = FlutterRunTestDriver(tempDir);
|
||||
tearDown(() async {
|
||||
await _flutter.stop();
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
|
||||
test('can step over statements', () async {
|
||||
await _flutter.run(withDebugger: true, startPaused: true);
|
||||
await _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine);
|
||||
await _flutter.resume();
|
||||
@ -39,11 +51,8 @@ void main() {
|
||||
final int expectedLine = _project.lineForStep(i);
|
||||
|
||||
expect(actualLine, equals(expectedLine),
|
||||
reason: 'After $i steps, debugger should stop at $expectedLine but stopped at $actualLine'
|
||||
);
|
||||
reason: 'After $i steps, debugger should stop at $expectedLine but stopped at $actualLine');
|
||||
}
|
||||
|
||||
await _flutter.stop();
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
}, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
|
||||
}
|
||||
|
@ -2,8 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Integration tests which invoke flutter instead of unit testing the code
|
||||
// will not produce meaningful coverage information - we can measure coverage
|
||||
// from the isolate running the test, but not from the isolate started via
|
||||
// the command line process.
|
||||
@Tags(<String>['no_coverage'])
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
@ -16,21 +20,22 @@ import 'test_data/tests_project.dart';
|
||||
import 'test_driver.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void batch1() {
|
||||
final BasicProject _project = BasicProject();
|
||||
void main() {
|
||||
group('flutter run expression evaluation', () {
|
||||
Directory tempDir;
|
||||
final BasicProject _project = BasicProject();
|
||||
FlutterRunTestDriver _flutter;
|
||||
|
||||
Future<void> initProject() async {
|
||||
setUp(() async {
|
||||
tempDir = createResolvedTempDirectorySync('run_expression_eval_test.');
|
||||
await _project.setUpIn(tempDir);
|
||||
_flutter = FlutterRunTestDriver(tempDir);
|
||||
}
|
||||
});
|
||||
|
||||
Future<void> cleanProject() async {
|
||||
tearDown(() async {
|
||||
await _flutter.stop();
|
||||
tryToDelete(tempDir);
|
||||
}
|
||||
});
|
||||
|
||||
Future<void> breakInBuildMethod(FlutterTestDriver flutter) async {
|
||||
await _flutter.breakAt(
|
||||
@ -46,103 +51,89 @@ void batch1() {
|
||||
);
|
||||
}
|
||||
|
||||
test('flutter run expression evaluation - can evaluate trivial expressions in top level function', () async {
|
||||
await initProject();
|
||||
test('can evaluate trivial expressions in top level function', () async {
|
||||
await _flutter.run(withDebugger: true);
|
||||
await breakInTopLevelFunction(_flutter);
|
||||
await evaluateTrivialExpressions(_flutter);
|
||||
await cleanProject();
|
||||
});
|
||||
|
||||
test('flutter run expression evaluation - can evaluate trivial expressions in build method', () async {
|
||||
await initProject();
|
||||
test('can evaluate trivial expressions in build method', () async {
|
||||
await _flutter.run(withDebugger: true);
|
||||
await breakInBuildMethod(_flutter);
|
||||
await evaluateTrivialExpressions(_flutter);
|
||||
await cleanProject();
|
||||
});
|
||||
|
||||
test('flutter run expression evaluation - can evaluate complex expressions in top level function', () async {
|
||||
await initProject();
|
||||
test('can evaluate complex expressions in top level function', () async {
|
||||
await _flutter.run(withDebugger: true);
|
||||
await breakInTopLevelFunction(_flutter);
|
||||
await evaluateComplexExpressions(_flutter);
|
||||
await cleanProject();
|
||||
});
|
||||
|
||||
test('flutter run expression evaluation - can evaluate complex expressions in build method', () async {
|
||||
await initProject();
|
||||
test('can evaluate complex expressions in build method', () async {
|
||||
await _flutter.run(withDebugger: true);
|
||||
await breakInBuildMethod(_flutter);
|
||||
await evaluateComplexExpressions(_flutter);
|
||||
await cleanProject();
|
||||
});
|
||||
|
||||
test('flutter run expression evaluation - can evaluate expressions returning complex objects in top level function', () async {
|
||||
await initProject();
|
||||
test('can evaluate expressions returning complex objects in top level function', () async {
|
||||
await _flutter.run(withDebugger: true);
|
||||
await breakInTopLevelFunction(_flutter);
|
||||
await evaluateComplexReturningExpressions(_flutter);
|
||||
await cleanProject();
|
||||
});
|
||||
|
||||
test('flutter run expression evaluation - can evaluate expressions returning complex objects in build method', () async {
|
||||
await initProject();
|
||||
test('can evaluate expressions returning complex objects in build method', () async {
|
||||
await _flutter.run(withDebugger: true);
|
||||
await breakInBuildMethod(_flutter);
|
||||
await evaluateComplexReturningExpressions(_flutter);
|
||||
await cleanProject();
|
||||
});
|
||||
}
|
||||
}, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
|
||||
|
||||
void batch2() {
|
||||
final TestsProject _project = TestsProject();
|
||||
group('flutter test expression evaluation', () {
|
||||
Directory tempDir;
|
||||
final TestsProject _project = TestsProject();
|
||||
FlutterTestTestDriver _flutter;
|
||||
|
||||
Future<void> initProject() async {
|
||||
setUp(() async {
|
||||
tempDir = createResolvedTempDirectorySync('test_expression_eval_test.');
|
||||
await _project.setUpIn(tempDir);
|
||||
_flutter = FlutterTestTestDriver(tempDir);
|
||||
}
|
||||
});
|
||||
|
||||
Future<void> cleanProject() async {
|
||||
await _flutter?.quit();
|
||||
tearDown(() async {
|
||||
await _flutter.quit();
|
||||
tryToDelete(tempDir);
|
||||
}
|
||||
});
|
||||
|
||||
test('flutter test expression evaluation - can evaluate trivial expressions in a test', () async {
|
||||
await initProject();
|
||||
test('can evaluate trivial expressions in a test', () async {
|
||||
await _flutter.test(
|
||||
withDebugger: true,
|
||||
beforeStart: () => _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine),
|
||||
);
|
||||
await _flutter.waitForPause();
|
||||
await evaluateTrivialExpressions(_flutter);
|
||||
await cleanProject();
|
||||
await _flutter.resume();
|
||||
});
|
||||
|
||||
test('flutter test expression evaluation - can evaluate complex expressions in a test', () async {
|
||||
await initProject();
|
||||
test('can evaluate complex expressions in a test', () async {
|
||||
await _flutter.test(
|
||||
withDebugger: true,
|
||||
beforeStart: () => _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine),
|
||||
);
|
||||
await _flutter.waitForPause();
|
||||
await evaluateComplexExpressions(_flutter);
|
||||
await cleanProject();
|
||||
await _flutter.resume();
|
||||
});
|
||||
|
||||
test('flutter test expression evaluation - can evaluate expressions returning complex objects in a test', () async {
|
||||
await initProject();
|
||||
test('can evaluate expressions returning complex objects in a test', () async {
|
||||
await _flutter.test(
|
||||
withDebugger: true,
|
||||
beforeStart: () => _flutter.addBreakpoint(_project.breakpointUri, _project.breakpointLine),
|
||||
);
|
||||
await _flutter.waitForPause();
|
||||
await evaluateComplexReturningExpressions(_flutter);
|
||||
await cleanProject();
|
||||
await _flutter.resume();
|
||||
});
|
||||
}, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
|
||||
}
|
||||
|
||||
Future<void> evaluateTrivialExpressions(FlutterTestDriver flutter) async {
|
||||
@ -173,8 +164,3 @@ Future<void> evaluateComplexReturningExpressions(FlutterTestDriver flutter) asyn
|
||||
final InstanceRef res = await flutter.evaluate(resp.id, r'"$year-$month-$day"');
|
||||
expect(res.valueAsString, equals('${now.year}-${now.month}-${now.day}'));
|
||||
}
|
||||
|
||||
void main() {
|
||||
batch1();
|
||||
batch2();
|
||||
}
|
||||
|
@ -2,8 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
// Integration tests which invoke flutter instead of unit testing the code
|
||||
// will not produce meaningful coverage information - we can measure coverage
|
||||
// from the isolate running the test, but not from the isolate started via
|
||||
// the command line process.
|
||||
@Tags(<String>['no_coverage'])
|
||||
import 'package:file/file.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
|
||||
@ -30,6 +33,7 @@ void main() {
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
|
||||
group('attached process', () {
|
||||
test('writes pid-file', () async {
|
||||
final File pidFile = tempDir.childFile('test.pid');
|
||||
await _flutterRun.run(withDebugger: true);
|
||||
@ -39,13 +43,11 @@ void main() {
|
||||
);
|
||||
expect(pidFile.existsSync(), isTrue);
|
||||
});
|
||||
|
||||
test('can hot reload', () async {
|
||||
await _flutterRun.run(withDebugger: true);
|
||||
await _flutterAttach.attach(_flutterRun.vmServicePort);
|
||||
await _flutterAttach.hotReload();
|
||||
});
|
||||
|
||||
test('can detach, reattach, hot reload', () async {
|
||||
await _flutterRun.run(withDebugger: true);
|
||||
await _flutterAttach.attach(_flutterRun.vmServicePort);
|
||||
@ -53,7 +55,6 @@ void main() {
|
||||
await _flutterAttach.attach(_flutterRun.vmServicePort);
|
||||
await _flutterAttach.hotReload();
|
||||
});
|
||||
|
||||
test('killing process behaves the same as detach ', () async {
|
||||
await _flutterRun.run(withDebugger: true);
|
||||
await _flutterAttach.attach(_flutterRun.vmServicePort);
|
||||
@ -62,4 +63,5 @@ void main() {
|
||||
await _flutterAttach.attach(_flutterRun.vmServicePort);
|
||||
await _flutterAttach.hotReload();
|
||||
});
|
||||
}, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
|
||||
}
|
||||
|
@ -2,6 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Integration tests which invoke flutter instead of unit testing the code
|
||||
// will not produce meaningful coverage information - we can measure coverage
|
||||
// from the isolate running the test, but not from the isolate started via
|
||||
// the command line process.
|
||||
@Tags(<String>['no_coverage'])
|
||||
import 'package:file/file.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
@ -13,6 +18,7 @@ import 'test_driver.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
group('flutter_run', () {
|
||||
Directory tempDir;
|
||||
final BasicProject _project = BasicProject();
|
||||
FlutterRunTestDriver _flutter;
|
||||
@ -28,7 +34,7 @@ void main() {
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
|
||||
test('flutter run reports an error if an invalid device is supplied', () async {
|
||||
test('reports an error if an invalid device is supplied', () async {
|
||||
// This test forces flutter to check for all possible devices to catch issues
|
||||
// like https://github.com/flutter/flutter/issues/21418 which were skipped
|
||||
// over because other integration tests run using flutter-tester which short-cuts
|
||||
@ -49,9 +55,10 @@ void main() {
|
||||
}
|
||||
});
|
||||
|
||||
test('flutter run writes pid-file', () async {
|
||||
test('writes pid-file', () async {
|
||||
final File pidFile = tempDir.childFile('test.pid');
|
||||
await _flutter.run(pidFile: pidFile);
|
||||
expect(pidFile.existsSync(), isTrue);
|
||||
});
|
||||
}, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
|
||||
}
|
||||
|
@ -2,6 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Integration tests which invoke flutter instead of unit testing the code
|
||||
// will not produce meaningful coverage information - we can measure coverage
|
||||
// from the isolate running the test, but not from the isolate started via
|
||||
// the command line process.
|
||||
@Tags(<String>['no_coverage'])
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:file/file.dart';
|
||||
@ -15,6 +20,7 @@ import 'test_driver.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
group('hot reload tests', () {
|
||||
Directory tempDir;
|
||||
final HotReloadProject _project = HotReloadProject();
|
||||
FlutterRunTestDriver _flutter;
|
||||
@ -148,4 +154,5 @@ void main() {
|
||||
await _flutter.resume();
|
||||
await subscription.cancel();
|
||||
});
|
||||
}, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
|
||||
}
|
||||
|
@ -2,6 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Integration tests which invoke flutter instead of unit testing the code
|
||||
// will not produce meaningful coverage information - we can measure coverage
|
||||
// from the isolate running the test, but not from the isolate started via
|
||||
// the command line process.
|
||||
@Tags(<String>['no_coverage'])
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:file/file.dart';
|
||||
@ -18,6 +23,7 @@ import 'test_utils.dart';
|
||||
const Duration requiredLifespan = Duration(seconds: 5);
|
||||
|
||||
void main() {
|
||||
group('flutter run', () {
|
||||
final BasicProject _project = BasicProject();
|
||||
FlutterRunTestDriver _flutter;
|
||||
Directory tempDir;
|
||||
@ -33,15 +39,16 @@ void main() {
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
|
||||
test('flutter run does not terminate when a debugger is attached', () async {
|
||||
test('does not terminate when a debugger is attached', () async {
|
||||
await _flutter.run(withDebugger: true);
|
||||
await Future<void>.delayed(requiredLifespan);
|
||||
expect(_flutter.hasExited, equals(false));
|
||||
});
|
||||
|
||||
test('fluter run does not terminate when a debugger is attached and pause-on-exceptions', () async {
|
||||
test('does not terminate when a debugger is attached and pause-on-exceptions', () async {
|
||||
await _flutter.run(withDebugger: true, pauseOnExceptions: true);
|
||||
await Future<void>.delayed(requiredLifespan);
|
||||
expect(_flutter.hasExited, equals(false));
|
||||
});
|
||||
}, timeout: const Timeout.factor(10), tags: <String>['integration']); // The DevFS sync takes a really long time, so these tests can be slow.
|
||||
}
|
||||
|
@ -127,6 +127,13 @@ Future<String> createProject(Directory temp, { List<String> arguments }) async {
|
||||
return projectPath;
|
||||
}
|
||||
|
||||
/// Test case timeout for tests involving remote calls to `pub get` or similar.
|
||||
const Timeout allowForRemotePubInvocation = Timeout.factor(10.0);
|
||||
|
||||
/// Test case timeout for tests involving creating a Flutter project with
|
||||
/// `--no-pub`. Use [allowForRemotePubInvocation] when creation involves `pub`.
|
||||
const Timeout allowForCreateFlutterProject = Timeout.factor(3.0);
|
||||
|
||||
Future<void> expectToolExitLater(Future<dynamic> future, Matcher messageMatcher) async {
|
||||
try {
|
||||
await future;
|
||||
|
@ -48,6 +48,7 @@ typedef ContextInitializer = void Function(AppContext testContext);
|
||||
void testUsingContext(
|
||||
String description,
|
||||
dynamic testMethod(), {
|
||||
Timeout timeout,
|
||||
Map<Type, Generator> overrides = const <Type, Generator>{},
|
||||
bool initializeFlutterRoot = true,
|
||||
String testOn,
|
||||
@ -136,7 +137,8 @@ void testUsingContext(
|
||||
},
|
||||
);
|
||||
});
|
||||
}, testOn: testOn, skip: skip);
|
||||
}, timeout: timeout ?? const Timeout(Duration(seconds: 60)),
|
||||
testOn: testOn, skip: skip);
|
||||
}
|
||||
|
||||
void _printBufferedErrors(AppContext testContext) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user