Skip to content

Commit

Permalink
[CP] Add migrator to upgrade gradle version when conflict with Androi…
Browse files Browse the repository at this point in the history
…d Studio bundled Java version is detected (and 3 others) (flutter#126093)

This is a cherry pick of the following four PRs (the first one depends
on changes made in the latter three).
1. flutter#125836
2. flutter#124771
3. flutter#123034
4. flutter#123644

For the first PR,
Original issue: flutter#122376
Cherry-pick issue: flutter#125693

*If you had to change anything in the [flutter/tests] repo, include a
link to the migration guide as per the [breaking change policy].*

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat

---------

Co-authored-by: Reid Baker <reidbaker@google.com>
Co-authored-by: Mitchell Goodwin <58190796+MitchellGoodwin@users.noreply.github.com>
Co-authored-by: Greg Spencer <gspencergoog@users.noreply.github.com>
Co-authored-by: Victoria Ashworth <vashworth@google.com>
Co-authored-by: Jackson Gardner <jacksongardner@google.com>
Co-authored-by: Rydmike <m.rydstrom@gmail.com>
Co-authored-by: keyonghan <54558023+keyonghan@users.noreply.github.com>
Co-authored-by: chunhtai <47866232+chunhtai@users.noreply.github.com>
Co-authored-by: Taha Tesser <tessertaha@gmail.com>
Co-authored-by: Ben Konyi <bkonyi@google.com>
Co-authored-by: engine-flutter-autoroll <engine-flutter-autoroll@skia.org>
Co-authored-by: hellohuanlin <41930132+hellohuanlin@users.noreply.github.com>
Co-authored-by: Danny Tuppeny <danny@tuppeny.com>
Co-authored-by: Chris Bracken <chris@bracken.jp>
Co-authored-by: Kate Lovett <katelovett@google.com>
Co-authored-by: Michael Goderbauer <goderbauer@google.com>
Co-authored-by: Elias Yishak <42216813+eliasyishak@users.noreply.github.com>
Co-authored-by: Christopher Fujino <fujino@google.com>
Co-authored-by: Andrew Kolos <andrewrkolos@gmail.com>
  • Loading branch information
20 people authored and ead committed Sep 14, 2023
1 parent 367f9ea commit e839042
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 0 deletions.
Expand Up @@ -447,6 +447,9 @@ class FakeAndroidSdk extends Fake implements AndroidSdk {

@override
final Directory directory;

@override
String? get javaHome => 'java';
}

class FakeAndroidStudio extends Fake implements AndroidStudio {
Expand Down
Expand Up @@ -230,4 +230,7 @@ class FakeAndroidSdk extends Fake implements AndroidSdk {

@override
final Directory directory;

@override
String? get javaHome => 'java';
}
Expand Up @@ -1303,6 +1303,177 @@ void main() {
ProcessManager: () => FakeProcessManager.any(),
});
});

group('latestValid', () {
late Platform platform;
late FileSystem fileSystem;

setUp(() {
platform = FakePlatform(
operatingSystem: 'windows',
environment: <String, String>{
'LOCALAPPDATA': r'C:\Users\Dash\AppData\Local',
}
);
fileSystem = MemoryFileSystem.test(style: FileSystemStyle.windows);
});

testUsingContext('choses the install with the latest version', () {
const List<String> versions = <String> [
'4.0',
'2022.0',
'3.1',
];

for (final String version in versions) {
fileSystem.file('C:\\Users\\Dash\\AppData\\Local\\Google\\AndroidStudio$version\\.home')
..createSync(recursive: true)
..writeAsStringSync('C:\\Program Files\\AndroidStudio$version');
fileSystem.directory('C:\\Program Files\\AndroidStudio$version')
.createSync(recursive: true);
}

expect(AndroidStudio.allInstalled().length, 3);
expect(AndroidStudio.latestValid()!.version, Version(2022, 0, 0));
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(),
});

testUsingContext('prefers installs with known versions over installs with unknown versions', () {
const List<String> versions = <String> [
'3.0',
'unknown',
];

for (final String version in versions) {
fileSystem.file('C:\\Users\\Dash\\AppData\\Local\\Google\\AndroidStudio$version\\.home')
..createSync(recursive: true)
..writeAsStringSync('C:\\Program Files\\AndroidStudio$version');
fileSystem.directory('C:\\Program Files\\AndroidStudio$version')
.createSync(recursive: true);
}

expect(AndroidStudio.allInstalled().length, 2);
expect(AndroidStudio.latestValid()!.version, Version(3, 0, 0));
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(),
});

testUsingContext('choses install with lexicographically greatest directory if no installs have known versions', () {
const List<String> versions = <String> [
'Apple',
'Zucchini',
'Banana',
];

for (final String version in versions) {
fileSystem.file('C:\\Users\\Dash\\AppData\\Local\\Google\\AndroidStudio$version\\.home')
..createSync(recursive: true)
..writeAsStringSync('C:\\Program Files\\AndroidStudio$version');
fileSystem.directory('C:\\Program Files\\AndroidStudio$version')
.createSync(recursive: true);
}

expect(AndroidStudio.allInstalled().length, 3);
expect(AndroidStudio.latestValid()!.directory, r'C:\Program Files\AndroidStudioZucchini');
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(),
});

testUsingContext('choses install with lexicographically greatest directory if all installs have the same version', () {
fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudioPreview4.0\.home')
..createSync(recursive: true)
..writeAsStringSync(r'C:\Program Files\AndroidStudioPreview4.0');
fileSystem.directory(r'C:\Program Files\AndroidStudioPreview4.0')
.createSync(recursive: true);

fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio4.0\.home')
..createSync(recursive: true)
..writeAsStringSync(r'C:\Program Files\AndroidStudio4.0');
fileSystem.directory(r'C:\Program Files\AndroidStudio4.0')
.createSync(recursive: true);

expect(AndroidStudio.allInstalled().length, 2);
expect(AndroidStudio.latestValid()!.directory, contains('Preview'));
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(),
});

testUsingContext('always chooses the install configured by --android-studio-dir, even if the install is invalid', () {
const String configuredAndroidStudioDir = r'C:\Users\Dash\Desktop\android-studio';
globals.config.setValue('android-studio-dir', configuredAndroidStudioDir);

// The directory exists, but nothing is inside.
fileSystem.directory(configuredAndroidStudioDir).createSync(recursive: true);
(globals.processManager as FakeProcessManager).excludedExecutables.add(
fileSystem.path.join(configuredAndroidStudioDir, 'jre', 'bin', 'java'),
);

const List<String> validVersions = <String> [
'4.0',
'2.0',
'3.1',
];

for (final String version in validVersions) {
fileSystem.file('C:\\Users\\Dash\\AppData\\Local\\Google\\AndroidStudio$version\\.home')
..createSync(recursive: true)
..writeAsStringSync('C:\\Program Files\\AndroidStudio$version');
fileSystem.directory('C:\\Program Files\\AndroidStudio$version')
.createSync(recursive: true);
}

const List<String> validJavaPaths = <String>[
r'C:\Program Files\AndroidStudio4.0\jre\bin\java',
r'C:\Program Files\AndroidStudio2.0\jre\bin\java',
r'C:\Program Files\AndroidStudio3.1\jre\bin\java',
];

for (final String javaPath in validJavaPaths) {
(globals.processManager as FakeProcessManager).addCommand(FakeCommand(
command: <String>[
globals.fs.path.join(javaPath),
'-version',
],
));
}

expect(AndroidStudio.allInstalled().length, 4);
final AndroidStudio chosenInstall = AndroidStudio.latestValid()!;
expect(chosenInstall.directory, configuredAndroidStudioDir);
expect(chosenInstall.isValid, false);
}, overrides: <Type, Generator>{
Config: () => Config.test(),
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.empty(),
});

testUsingContext('throws a ToolExit if --android-studio-dir is configured but the directory does not exist', () async {
const String configuredAndroidStudioDir = r'C:\Users\Dash\Desktop\android-studio';
globals.config.setValue('android-studio-dir', configuredAndroidStudioDir);

expect(fileSystem.directory(configuredAndroidStudioDir).existsSync(), false);
expect(() => AndroidStudio.latestValid(), throwsA(
(dynamic e) => e is ToolExit &&
e.message!.startsWith('Could not find the Android Studio installation at the manually configured path')
)
);
}, overrides: <Type, Generator>{
Config: () => Config.test(),
FileSystem: () => fileSystem,
Platform: () => platform,
ProcessManager: () => FakeProcessManager.any(),
});
});
}

class FakePlistUtils extends Fake implements PlistParser {
Expand Down

0 comments on commit e839042

Please sign in to comment.