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

[flutter_tools] migrate gradle errors and project test to null safety (#110530)

parent 2f3ba1a3
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/android/gradle_errors.dart';
......@@ -13,8 +11,8 @@ import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/project.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/context.dart';
......@@ -22,6 +20,14 @@ import '../../src/fake_process_manager.dart';
import '../../src/fakes.dart';
void main() {
late FileSystem fileSystem;
late FakeProcessManager processManager;
setUp(() {
fileSystem = MemoryFileSystem.test();
processManager = FakeProcessManager.empty();
});
group('gradleErrors', () {
testWithoutContext('list of errors', () {
// If you added a new Gradle error, please update this test.
......@@ -64,7 +70,12 @@ at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:128)
at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
expect(formatTestErrorMessage(errorMessage, networkErrorHandler), isTrue);
expect(await networkErrorHandler.handler(), equals(GradleBuildStatus.retry));
expect(await networkErrorHandler.handler(
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
usesAndroidX: true,
), equals(GradleBuildStatus.retry));
expect(testLogger.errorText,
contains(
......@@ -72,8 +83,8 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('retries if gradle fails downloading with proxy error', () async {
......@@ -94,7 +105,12 @@ at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:128)
at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
expect(formatTestErrorMessage(errorMessage, networkErrorHandler), isTrue);
expect(await networkErrorHandler.handler(), equals(GradleBuildStatus.retry));
expect(await networkErrorHandler.handler(
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
usesAndroidX: true,
), equals(GradleBuildStatus.retry));
expect(testLogger.errorText,
contains(
......@@ -102,8 +118,8 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('retries if gradle times out waiting for exclusive access to zip', () async {
......@@ -115,7 +131,12 @@ Exception in thread "main" java.lang.RuntimeException: Timeout of 120000 reached
at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
expect(formatTestErrorMessage(errorMessage, networkErrorHandler), isTrue);
expect(await networkErrorHandler.handler(), equals(GradleBuildStatus.retry));
expect(await networkErrorHandler.handler(
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
usesAndroidX: true,
), equals(GradleBuildStatus.retry));
expect(testLogger.errorText,
contains(
......@@ -123,8 +144,8 @@ Exception in thread "main" java.lang.RuntimeException: Timeout of 120000 reached
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('retries if remote host closes connection', () async {
......@@ -152,7 +173,12 @@ Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host clos
at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
expect(formatTestErrorMessage(errorMessage, networkErrorHandler), isTrue);
expect(await networkErrorHandler.handler(), equals(GradleBuildStatus.retry));
expect(await networkErrorHandler.handler(
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
usesAndroidX: true,
), equals(GradleBuildStatus.retry));
expect(testLogger.errorText,
contains(
......@@ -160,8 +186,8 @@ Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host clos
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('retries if file opening fails', () async {
......@@ -181,7 +207,12 @@ Exception in thread "main" java.io.FileNotFoundException: https://downloads.grad
at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
expect(formatTestErrorMessage(errorMessage, networkErrorHandler), isTrue);
expect(await networkErrorHandler.handler(), equals(GradleBuildStatus.retry));
expect(await networkErrorHandler.handler(
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
usesAndroidX: true,
), equals(GradleBuildStatus.retry));
expect(testLogger.errorText,
contains(
......@@ -189,8 +220,8 @@ Exception in thread "main" java.io.FileNotFoundException: https://downloads.grad
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('retries if the connection is reset', () async {
......@@ -221,7 +252,12 @@ Exception in thread "main" java.net.SocketException: Connection reset
at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
expect(formatTestErrorMessage(errorMessage, networkErrorHandler), isTrue);
expect(await networkErrorHandler.handler(), equals(GradleBuildStatus.retry));
expect(await networkErrorHandler.handler(
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
usesAndroidX: true,
), equals(GradleBuildStatus.retry));
expect(testLogger.errorText,
contains(
......@@ -229,8 +265,8 @@ Exception in thread "main" java.net.SocketException: Connection reset
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('retries if Gradle could not get a resource', () async {
......@@ -248,7 +284,12 @@ A problem occurred configuring root project 'android'.
> Could not GET 'https://jcenter.bintray.com/net/sf/proguard/proguard-parent/6.0.3/proguard-parent-6.0.3.pom'. Received status code 504 from server: Gateway Time-out''';
expect(formatTestErrorMessage(errorMessage, networkErrorHandler), isTrue);
expect(await networkErrorHandler.handler(), equals(GradleBuildStatus.retry));
expect(await networkErrorHandler.handler(
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
usesAndroidX: true,
), equals(GradleBuildStatus.retry));
expect(testLogger.errorText,
contains(
......@@ -256,8 +297,8 @@ A problem occurred configuring root project 'android'.
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('retries if Gradle could not get a resource (non-Gateway)', () async {
......@@ -279,7 +320,12 @@ A problem occurred configuring root project 'android'.
> Remote host closed connection during handshake''';
expect(formatTestErrorMessage(errorMessage, networkErrorHandler), isTrue);
expect(await networkErrorHandler.handler(), equals(GradleBuildStatus.retry));
expect(await networkErrorHandler.handler(
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
usesAndroidX: true,
), equals(GradleBuildStatus.retry));
expect(testLogger.errorText,
contains(
......@@ -287,8 +333,8 @@ A problem occurred configuring root project 'android'.
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -318,7 +364,7 @@ Execution failed for task ':app:mergeDexDebug'.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html''';
expect(formatTestErrorMessage(errorMessage, multidexErrorHandler), isTrue);
expect(await multidexErrorHandler.handler(project: FlutterProject.fromDirectory(globals.fs.currentDirectory), multidexEnabled: true), equals(GradleBuildStatus.exit));
expect(await multidexErrorHandler.handler(project: FlutterProject.fromDirectory(fileSystem.currentDirectory), multidexEnabled: true, usesAndroidX: true, line: ''), equals(GradleBuildStatus.exit));
expect(testLogger.statusText,
contains(
......@@ -336,8 +382,8 @@ Execution failed for task ':app:mergeDexDebug'.
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('retries if multidex support enabled', () async {
const String errorMessage = r'''
......@@ -363,7 +409,7 @@ Execution failed for task ':app:mergeDexDebug'.
The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html''';
final File manifest = globals.fs.currentDirectory
final File manifest = fileSystem.currentDirectory
.childDirectory('android')
.childDirectory('app')
.childDirectory('src')
......@@ -382,7 +428,7 @@ Execution failed for task ':app:mergeDexDebug'.
''', flush: true);
expect(formatTestErrorMessage(errorMessage, multidexErrorHandler), isTrue);
expect(await multidexErrorHandler.handler(project: FlutterProject.fromDirectory(globals.fs.currentDirectory), multidexEnabled: true), equals(GradleBuildStatus.retry));
expect(await multidexErrorHandler.handler(project: FlutterProject.fromDirectory(fileSystem.currentDirectory), multidexEnabled: true, line: '', usesAndroidX: true), equals(GradleBuildStatus.retry));
expect(testLogger.statusText,
contains(
......@@ -395,8 +441,8 @@ Execution failed for task ':app:mergeDexDebug'.
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
AnsiTerminal: () => _TestPromptTerminal('y'),
});
......@@ -424,7 +470,7 @@ Execution failed for task ':app:mergeDexDebug'.
The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html''';
final File manifest = globals.fs.currentDirectory
final File manifest = fileSystem.currentDirectory
.childDirectory('android')
.childDirectory('app')
.childDirectory('src')
......@@ -443,7 +489,7 @@ Execution failed for task ':app:mergeDexDebug'.
''', flush: true);
expect(formatTestErrorMessage(errorMessage, multidexErrorHandler), isTrue);
expect(await multidexErrorHandler.handler(project: FlutterProject.fromDirectory(globals.fs.currentDirectory), multidexEnabled: true), equals(GradleBuildStatus.exit));
expect(await multidexErrorHandler.handler(project: FlutterProject.fromDirectory(fileSystem.currentDirectory), multidexEnabled: true, line: '', usesAndroidX: true), equals(GradleBuildStatus.exit));
expect(testLogger.statusText,
contains(
......@@ -461,8 +507,8 @@ Execution failed for task ':app:mergeDexDebug'.
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
AnsiTerminal: () => _TestPromptTerminal('n'),
});
......@@ -491,7 +537,7 @@ Execution failed for task ':app:mergeDexDebug'.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html''';
expect(formatTestErrorMessage(errorMessage, multidexErrorHandler), isTrue);
expect(await multidexErrorHandler.handler(project: FlutterProject.fromDirectory(globals.fs.currentDirectory), multidexEnabled: false), equals(GradleBuildStatus.exit));
expect(await multidexErrorHandler.handler(project: FlutterProject.fromDirectory(fileSystem.currentDirectory), multidexEnabled: false, line: '', usesAndroidX: true), equals(GradleBuildStatus.exit));
expect(testLogger.statusText,
contains(
......@@ -499,8 +545,8 @@ Execution failed for task ':app:mergeDexDebug'.
)
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -511,7 +557,12 @@ Permission denied
Command: /home/android/gradlew assembleRelease
''';
expect(formatTestErrorMessage(errorMessage, permissionDeniedErrorHandler), isTrue);
expect(await permissionDeniedErrorHandler.handler(), equals(GradleBuildStatus.exit));
expect(await permissionDeniedErrorHandler.handler(
usesAndroidX: true,
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
), equals(GradleBuildStatus.exit));
expect(
testLogger.statusText,
......@@ -541,7 +592,12 @@ Command: /home/android/gradlew assembleRelease
});
testUsingContext('handler', () async {
expect(await permissionDeniedErrorHandler.handler(), equals(GradleBuildStatus.exit));
expect(await permissionDeniedErrorHandler.handler(
usesAndroidX: true,
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
), equals(GradleBuildStatus.exit));
expect(
testLogger.statusText,
......@@ -574,7 +630,9 @@ Command: /home/android/gradlew assembleRelease
testUsingContext('handler', () async {
await licenseNotAcceptedHandler.handler(
line: 'You have not accepted the license agreements of the following SDK components: [foo, bar]',
project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
usesAndroidX: true,
multidexEnabled: true,
);
expect(
......@@ -594,12 +652,6 @@ Command: /home/android/gradlew assembleRelease
});
group('flavor undefined', () {
FakeProcessManager fakeProcessManager;
setUp(() {
fakeProcessManager = FakeProcessManager.empty();
});
testWithoutContext('pattern', () {
expect(
flavorUndefinedHandler.test(
......@@ -628,7 +680,7 @@ Command: /home/android/gradlew assembleRelease
});
testUsingContext('handler - with flavor', () async {
fakeProcessManager.addCommand(const FakeCommand(
processManager.addCommand(const FakeCommand(
command: <String>[
'gradlew',
'app:tasks' ,
......@@ -649,7 +701,10 @@ assembleFooTest
));
await flavorUndefinedHandler.handler(
project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
usesAndroidX: true,
line: '',
multidexEnabled: true,
);
expect(
......@@ -671,16 +726,16 @@ assembleFooTest
'└─────────────────────────────────────────────────────────────────────────────────────────────────┘\n'
)
);
expect(fakeProcessManager, hasNoRemainingExpectations);
expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'),
ProcessManager: () => fakeProcessManager,
FileSystem: () => MemoryFileSystem.test(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
testUsingContext('handler - without flavor', () async {
fakeProcessManager.addCommand(const FakeCommand(
processManager.addCommand(const FakeCommand(
command: <String>[
'gradlew',
'app:tasks' ,
......@@ -695,7 +750,10 @@ assembleProfile
));
await flavorUndefinedHandler.handler(
project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
usesAndroidX: true,
line: '',
multidexEnabled: true,
);
expect(
......@@ -710,12 +768,12 @@ assembleProfile
'└───────────────────────────────────────────────────────────────────────────────────────────────┘\n'
)
);
expect(fakeProcessManager, hasNoRemainingExpectations);
expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'),
ProcessManager: () => fakeProcessManager,
FileSystem: () => MemoryFileSystem.test(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -732,7 +790,9 @@ assembleProfile
testUsingContext('suggestion', () async {
await minSdkVersionHandler.handler(
line: stdoutLine,
project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
usesAndroidX: true,
multidexEnabled: true,
);
expect(
......@@ -759,8 +819,8 @@ assembleProfile
}, overrides: <Type, Generator>{
GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -777,7 +837,10 @@ assembleProfile
testUsingContext('suggestion', () async {
await transformInputIssueHandler.handler(
project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
usesAndroidX: true,
line: '',
multidexEnabled: true,
);
expect(
......@@ -798,8 +861,8 @@ assembleProfile
}, overrides: <Type, Generator>{
GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -819,7 +882,10 @@ Execution failed for task ':app:generateDebugFeatureTransitiveDeps'.
testUsingContext('suggestion', () async {
await lockFileDepMissingHandler.handler(
project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
usesAndroidX: true,
line: '',
multidexEnabled: true,
);
expect(
......@@ -836,8 +902,8 @@ Execution failed for task ':app:generateDebugFeatureTransitiveDeps'.
}, overrides: <Type, Generator>{
GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -855,7 +921,10 @@ Execution failed for task ':app:generateDebugFeatureTransitiveDeps'.
testUsingContext('suggestion', () async {
await incompatibleKotlinVersionHandler.handler(
project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
usesAndroidX: true,
line: '',
multidexEnabled: true,
);
expect(
......@@ -873,8 +942,8 @@ Execution failed for task ':app:generateDebugFeatureTransitiveDeps'.
}, overrides: <Type, Generator>{
GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -895,7 +964,9 @@ A problem occurred evaluating project ':app'.
testUsingContext('suggestion', () async {
await outdatedGradleHandler.handler(
line: errorMessage,
project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
usesAndroidX: true,
multidexEnabled: true,
);
expect(
......@@ -918,8 +989,8 @@ A problem occurred evaluating project ':app'.
}, overrides: <Type, Generator>{
GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -952,7 +1023,9 @@ Execution failed for task ':app:checkDebugAarMetadata'.
testUsingContext('suggestion', () async {
await minCompileSdkVersionHandler.handler(
line: errorMessage,
project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
usesAndroidX: true,
multidexEnabled: true,
);
expect(
......@@ -971,8 +1044,8 @@ Execution failed for task ':app:checkDebugAarMetadata'.
}, overrides: <Type, Generator>{
GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -994,7 +1067,12 @@ A problem occurred evaluating project ':flutter'.
});
testUsingContext('suggestion', () async {
await jvm11RequiredHandler.handler();
await jvm11RequiredHandler.handler(
project: FakeFlutterProject(),
usesAndroidX: true,
line: '',
multidexEnabled: true,
);
expect(
testLogger.statusText,
......@@ -1013,8 +1091,8 @@ A problem occurred evaluating project ':flutter'.
}, overrides: <Type, Generator>{
GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -1069,7 +1147,12 @@ at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:108)'''
});
testUsingContext('suggestion', () async {
final GradleBuildStatus status = await sslExceptionHandler.handler();
final GradleBuildStatus status = await sslExceptionHandler.handler(
project: FakeFlutterProject(),
usesAndroidX: true,
line: '',
multidexEnabled: true,
);
expect(status, GradleBuildStatus.retry);
expect(testLogger.errorText,
......@@ -1080,8 +1163,8 @@ at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:108)'''
}, overrides: <Type, Generator>{
GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
});
});
......@@ -1108,12 +1191,17 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)'''
});
testUsingContext('suggestion', () async {
globals.fs.file('foo/.gradle/fizz.zip').createSync(recursive: true);
fileSystem.file('foo/.gradle/fizz.zip').createSync(recursive: true);
final GradleBuildStatus result = await zipExceptionHandler.handler();
final GradleBuildStatus result = await zipExceptionHandler.handler(
project: FakeFlutterProject(),
usesAndroidX: true,
line: '',
multidexEnabled: true,
);
expect(result, equals(GradleBuildStatus.retry));
expect(globals.fs.file('foo/.gradle/fizz.zip'), exists);
expect(fileSystem.file('foo/.gradle/fizz.zip'), exists);
expect(
testLogger.errorText,
contains(
......@@ -1123,18 +1211,23 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)'''
expect(testLogger.statusText, '');
}, overrides: <Type, Generator>{
Platform: () => FakePlatform(environment: <String, String>{'HOME': 'foo/'}),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
BotDetector: () => const FakeBotDetector(false),
});
testUsingContext('suggestion if running as bot', () async {
globals.fs.file('foo/.gradle/fizz.zip').createSync(recursive: true);
fileSystem.file('foo/.gradle/fizz.zip').createSync(recursive: true);
final GradleBuildStatus result = await zipExceptionHandler.handler();
final GradleBuildStatus result = await zipExceptionHandler.handler(
project: FakeFlutterProject(),
usesAndroidX: true,
line: '',
multidexEnabled: true,
);
expect(result, equals(GradleBuildStatus.retry));
expect(globals.fs.file('foo/.gradle/fizz.zip'), isNot(exists));
expect(fileSystem.file('foo/.gradle/fizz.zip'), isNot(exists));
expect(
testLogger.errorText,
......@@ -1148,18 +1241,23 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)'''
);
}, overrides: <Type, Generator>{
Platform: () => FakePlatform(environment: <String, String>{'HOME': 'foo/'}),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
BotDetector: () => const FakeBotDetector(true),
});
testUsingContext('suggestion if stdin has terminal and user entered y', () async {
globals.fs.file('foo/.gradle/fizz.zip').createSync(recursive: true);
fileSystem.file('foo/.gradle/fizz.zip').createSync(recursive: true);
final GradleBuildStatus result = await zipExceptionHandler.handler();
final GradleBuildStatus result = await zipExceptionHandler.handler(
line: '',
usesAndroidX: true,
multidexEnabled: true,
project: FakeFlutterProject(),
);
expect(result, equals(GradleBuildStatus.retry));
expect(globals.fs.file('foo/.gradle/fizz.zip'), isNot(exists));
expect(fileSystem.file('foo/.gradle/fizz.zip'), isNot(exists));
expect(
testLogger.errorText,
contains(
......@@ -1172,19 +1270,24 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)'''
);
}, overrides: <Type, Generator>{
Platform: () => FakePlatform(environment: <String, String>{'HOME': 'foo/'}),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
AnsiTerminal: () => _TestPromptTerminal('y'),
BotDetector: () => const FakeBotDetector(false),
});
testUsingContext('suggestion if stdin has terminal and user entered n', () async {
globals.fs.file('foo/.gradle/fizz.zip').createSync(recursive: true);
fileSystem.file('foo/.gradle/fizz.zip').createSync(recursive: true);
final GradleBuildStatus result = await zipExceptionHandler.handler();
final GradleBuildStatus result = await zipExceptionHandler.handler(
line: '',
usesAndroidX: true,
multidexEnabled: true,
project: FakeFlutterProject(),
);
expect(result, equals(GradleBuildStatus.retry));
expect(globals.fs.file('foo/.gradle/fizz.zip'), exists);
expect(fileSystem.file('foo/.gradle/fizz.zip'), exists);
expect(
testLogger.errorText,
contains(
......@@ -1194,8 +1297,8 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)'''
expect(testLogger.statusText, '');
}, overrides: <Type, Generator>{
Platform: () => FakePlatform(environment: <String, String>{'HOME': 'foo/'}),
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(),
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
AnsiTerminal: () => _TestPromptTerminal('n'),
BotDetector: () => const FakeBotDetector(false),
});
......@@ -1217,7 +1320,7 @@ Platform fakePlatform(String name) {
);
}
class FakeGradleUtils extends GradleUtils {
class FakeGradleUtils extends Fake implements GradleUtils {
@override
String getExecutable(FlutterProject project) {
return 'gradlew';
......@@ -1226,21 +1329,24 @@ class FakeGradleUtils extends GradleUtils {
/// Simple terminal that returns the specified string when
/// promptForCharInput is called.
class _TestPromptTerminal extends AnsiTerminal {
class _TestPromptTerminal extends Fake implements AnsiTerminal {
_TestPromptTerminal(this.promptResult);
final String promptResult;
@override
Future<String> promptForCharInput(List<String> acceptedCharacters, {
Logger logger,
String prompt,
int defaultChoiceIndex,
bool get stdinHasTerminal => true;
@override
Future<String> promptForCharInput(
List<String> acceptedCharacters, {
required Logger logger,
String? prompt,
int? defaultChoiceIndex,
bool displayAcceptedCharacters = true,
}) {
return Future<String>.value(promptResult);
}
@override
bool get stdinHasTerminal => true;
}
class FakeFlutterProject extends Fake implements FlutterProject {}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
......@@ -32,13 +30,6 @@ void main() {
group('Project', () {
group('construction', () {
_testInMemory('fails on null directory', () async {
expect(
() => FlutterProject.fromDirectory(null),
throwsAssertionError,
);
});
testWithoutContext('invalid utf8 throws a tool exit', () {
final FileSystem fileSystem = MemoryFileSystem.test();
final FlutterProjectFactory projectFactory = FlutterProjectFactory(
......@@ -226,7 +217,8 @@ void main() {
// v1 embedding, as opposed to having <meta-data
// android:name="flutterEmbedding" android:value="2" />.
project.checkForDeprecation(deprecationBehavior: DeprecationBehavior.none);
// Default is "DeprecationBehavior.none"
project.checkForDeprecation();
expect(testLogger.statusText, isEmpty);
});
_testInMemory('Android project not on v2 embedding ignore continues', () async {
......@@ -350,8 +342,8 @@ void main() {
final FlutterManifest manifest = FlutterManifest.createFromString('''
name: test
version: 1.0.0+3
''', logger: BufferLogger.test());
final FlutterProject project = FlutterProject(fileSystem.systemTempDirectory,manifest,manifest);
''', logger: BufferLogger.test())!;
final FlutterProject project = FlutterProject(fileSystem.systemTempDirectory, manifest, manifest);
final Map<String, dynamic> versionInfo = jsonDecode(project.getVersionInfo()) as Map<String, dynamic>;
expect(versionInfo['app_name'],'test');
expect(versionInfo['version'],'1.0.0');
......@@ -397,9 +389,9 @@ void main() {
});
group('language', () {
XcodeProjectInterpreter xcodeProjectInterpreter;
MemoryFileSystem fs;
FlutterProjectFactory flutterProjectFactory;
late XcodeProjectInterpreter xcodeProjectInterpreter;
late MemoryFileSystem fs;
late FlutterProjectFactory flutterProjectFactory;
setUp(() {
fs = MemoryFileSystem.test();
xcodeProjectInterpreter = XcodeProjectInterpreter.test(processManager: FakeProcessManager.any());
......@@ -434,14 +426,14 @@ apply plugin: 'kotlin-android'
});
group('product bundle identifier', () {
MemoryFileSystem fs;
FakePlistParser testPlistUtils;
MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
FlutterProjectFactory flutterProjectFactory;
late MemoryFileSystem fs;
late FakePlistParser testPlistUtils;
late FakeXcodeProjectInterpreter xcodeProjectInterpreter;
late FlutterProjectFactory flutterProjectFactory;
setUp(() {
fs = MemoryFileSystem.test();
testPlistUtils = FakePlistParser();
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
xcodeProjectInterpreter = FakeXcodeProjectInterpreter();
flutterProjectFactory = FlutterProjectFactory(
fileSystem: fs,
logger: logger,
......@@ -453,7 +445,7 @@ apply plugin: 'kotlin-android'
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
PlistParser: () => testPlistUtils,
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
XcodeProjectInterpreter: () => xcodeProjectInterpreter,
FlutterProjectFactory: () => flutterProjectFactory,
});
}
......@@ -466,16 +458,18 @@ apply plugin: 'kotlin-android'
testWithMocks('from build settings, if no plist', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
mockXcodeProjectInterpreter.buildSettings = <String, String>{
xcodeProjectInterpreter.buildSettings = <String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
};
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
expect(await project.ios.productBundleIdentifier(null), 'io.flutter.someProject');
});
testWithMocks('from project file, if no plist or build settings', () async {
final FlutterProject project = await someProject();
xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
addIosProjectFile(project.directory, projectFileContent: () {
return projectFileWithBundleId('io.flutter.someProject');
});
......@@ -492,10 +486,10 @@ apply plugin: 'kotlin-android'
testWithMocks('from build settings and plist, if default variable', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
mockXcodeProjectInterpreter.buildSettings = <String, String>{
xcodeProjectInterpreter.buildSettings = <String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
};
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
testPlistUtils.setProperty('CFBundleIdentifier', r'$(PRODUCT_BUNDLE_IDENTIFIER)');
expect(await project.ios.productBundleIdentifier(null), 'io.flutter.someProject');
......@@ -505,11 +499,11 @@ apply plugin: 'kotlin-android'
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
project.ios.defaultHostInfoPlist.createSync(recursive: true);
mockXcodeProjectInterpreter.buildSettings = <String, String>{
xcodeProjectInterpreter.buildSettings = <String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
'SUFFIX': 'suffix',
};
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
testPlistUtils.setProperty('CFBundleIdentifier', r'$(PRODUCT_BUNDLE_IDENTIFIER).$(SUFFIX)');
expect(await project.ios.productBundleIdentifier(null), 'io.flutter.someProject.suffix');
......@@ -518,7 +512,7 @@ apply plugin: 'kotlin-android'
testWithMocks('fails with no flavor and defined schemes', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['free', 'paid'], logger);
xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['free', 'paid'], logger);
await expectToolExitLater(
project.ios.productBundleIdentifier(null),
......@@ -529,10 +523,10 @@ apply plugin: 'kotlin-android'
testWithMocks('handles case insensitive flavor', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
mockXcodeProjectInterpreter.buildSettings = <String, String>{
xcodeProjectInterpreter.buildSettings = <String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject',
};
mockXcodeProjectInterpreter.xcodeProjectInfo =XcodeProjectInfo(<String>[], <String>[], <String>['Free'], logger);
xcodeProjectInterpreter.xcodeProjectInfo =XcodeProjectInfo(<String>[], <String>[], <String>['Free'], logger);
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, 'free', treeShakeIcons: false);
expect(await project.ios.productBundleIdentifier(buildInfo), 'io.flutter.someProject');
......@@ -541,7 +535,7 @@ apply plugin: 'kotlin-android'
testWithMocks('fails with flavor and default schemes', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
mockXcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, 'free', treeShakeIcons: false);
await expectToolExitLater(
......@@ -552,6 +546,7 @@ apply plugin: 'kotlin-android'
testWithMocks('empty surrounded by quotes', () async {
final FlutterProject project = await someProject();
xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
addIosProjectFile(project.directory, projectFileContent: () {
return projectFileWithBundleId('', qualifier: '"');
});
......@@ -560,6 +555,7 @@ apply plugin: 'kotlin-android'
testWithMocks('surrounded by double quotes', () async {
final FlutterProject project = await someProject();
xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
addIosProjectFile(project.directory, projectFileContent: () {
return projectFileWithBundleId('io.flutter.someProject', qualifier: '"');
});
......@@ -568,6 +564,7 @@ apply plugin: 'kotlin-android'
testWithMocks('surrounded by single quotes', () async {
final FlutterProject project = await someProject();
xcodeProjectInterpreter.xcodeProjectInfo = XcodeProjectInfo(<String>[], <String>[], <String>['Runner'], logger);
addIosProjectFile(project.directory, projectFileContent: () {
return projectFileWithBundleId('io.flutter.someProject', qualifier: "'");
});
......@@ -576,11 +573,11 @@ apply plugin: 'kotlin-android'
});
group('application bundle name', () {
MemoryFileSystem fs;
MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
late MemoryFileSystem fs;
late FakeXcodeProjectInterpreter mockXcodeProjectInterpreter;
setUp(() {
fs = MemoryFileSystem.test();
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
mockXcodeProjectInterpreter = FakeXcodeProjectInterpreter();
});
testUsingContext('app product name defaults to Runner.app', () async {
......@@ -681,14 +678,14 @@ apply plugin: 'kotlin-android'
});
});
group('watch companion', () {
MemoryFileSystem fs;
FakePlistParser testPlistParser;
MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
FlutterProjectFactory flutterProjectFactory;
late MemoryFileSystem fs;
late FakePlistParser testPlistParser;
late FakeXcodeProjectInterpreter mockXcodeProjectInterpreter;
late FlutterProjectFactory flutterProjectFactory;
setUp(() {
fs = MemoryFileSystem.test();
testPlistParser = FakePlistParser();
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
mockXcodeProjectInterpreter = FakeXcodeProjectInterpreter();
flutterProjectFactory = FlutterProjectFactory(
fileSystem: fs,
logger: logger,
......@@ -697,7 +694,7 @@ apply plugin: 'kotlin-android'
testUsingContext('cannot find bundle identifier', () async {
final FlutterProject project = await someProject();
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], null, '123'), isFalse);
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], BuildInfo.debug, '123'), isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
......@@ -716,7 +713,7 @@ apply plugin: 'kotlin-android'
testUsingContext('no Info.plist in target', () async {
final FlutterProject project = await someProject();
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], null, '123'), isFalse);
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], BuildInfo.debug, '123'), isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
......@@ -729,7 +726,7 @@ apply plugin: 'kotlin-android'
final FlutterProject project = await someProject();
project.ios.hostAppRoot.childDirectory('WatchTarget').childFile('Info.plist').createSync(recursive: true);
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], null, '123'), isFalse);
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], BuildInfo.debug, '123'), isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
......@@ -743,7 +740,7 @@ apply plugin: 'kotlin-android'
project.ios.hostAppRoot.childDirectory('WatchTarget').childFile('Info.plist').createSync(recursive: true);
testPlistParser.setProperty('WKCompanionAppBundleIdentifier', 'io.flutter.someOTHERproject');
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], null, '123'), isFalse);
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], BuildInfo.debug, '123'), isFalse);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
......@@ -758,7 +755,7 @@ apply plugin: 'kotlin-android'
project.ios.hostAppRoot.childDirectory('WatchTarget').childFile('Info.plist').createSync(recursive: true);
testPlistParser.setProperty('WKCompanionAppBundleIdentifier', 'io.flutter.someProject');
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], null, '123'), isTrue);
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], BuildInfo.debug, '123'), isTrue);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
......@@ -776,7 +773,7 @@ apply plugin: 'kotlin-android'
project.ios.hostAppRoot.childDirectory('WatchTarget').childFile('Info.plist').createSync(recursive: true);
testPlistParser.setProperty('WKCompanionAppBundleIdentifier', r'$(PRODUCT_BUNDLE_IDENTIFIER)');
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], null, '123'), isTrue);
expect(await project.ios.containsWatchCompanion(<String>['WatchTarget'], BuildInfo.debug, '123'), isTrue);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
......@@ -789,7 +786,7 @@ apply plugin: 'kotlin-android'
}
Future<FlutterProject> someProject({
String androidManifestOverride,
String? androidManifestOverride,
bool includePubspec = false,
}) async {
final Directory directory = globals.fs.directory('some_project');
......@@ -934,7 +931,7 @@ void _testInMemory(String description, Future<void> Function() testMethod) {
),
FlutterProjectFactory: () => FlutterProjectFactory(
fileSystem: testFileSystem,
logger: globals.logger ?? BufferLogger.test(),
logger: globals.logger,
),
},
);
......@@ -963,7 +960,7 @@ void expectNotExists(FileSystemEntity entity) {
expect(entity.existsSync(), isFalse);
}
void addIosProjectFile(Directory directory, {String Function() projectFileContent}) {
void addIosProjectFile(Directory directory, {required String Function() projectFileContent}) {
directory
.childDirectory('ios')
.childDirectory('Runner.xcodeproj')
......@@ -972,7 +969,7 @@ void addIosProjectFile(Directory directory, {String Function() projectFileConten
..writeAsStringSync(projectFileContent());
}
void addAndroidGradleFile(Directory directory, { String Function() gradleFileContent }) {
void addAndroidGradleFile(Directory directory, { required String Function() gradleFileContent }) {
directory
.childDirectory('android')
.childDirectory('app')
......@@ -1016,7 +1013,7 @@ flutter:
something_else:
''';
String projectFileWithBundleId(String id, {String qualifier}) {
String projectFileWithBundleId(String id, {String? qualifier}) {
return '''
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
......@@ -1066,20 +1063,20 @@ File androidPluginRegistrant(Directory parent) {
.childFile('GeneratedPluginRegistrant.java');
}
class MockXcodeProjectInterpreter extends Fake implements XcodeProjectInterpreter {
class FakeXcodeProjectInterpreter extends Fake implements XcodeProjectInterpreter {
Map<String, String> buildSettings = <String, String>{};
XcodeProjectInfo xcodeProjectInfo;
late XcodeProjectInfo xcodeProjectInfo;
@override
Future<Map<String, String>> getBuildSettings(String projectPath, {
XcodeProjectBuildContext buildContext,
XcodeProjectBuildContext? buildContext,
Duration timeout = const Duration(minutes: 1),
}) async {
return buildSettings;
}
@override
Future<XcodeProjectInfo> getInfo(String projectPath, {String projectFilename}) async {
Future<XcodeProjectInfo> getInfo(String projectPath, {String? projectFilename}) async {
return xcodeProjectInfo;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment