| // Copyright 2014 The Flutter 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 'package:file/memory.dart'; |
| import 'package:flutter_tools/src/android/android_studio.dart'; |
| import 'package:flutter_tools/src/base/common.dart'; |
| import 'package:flutter_tools/src/base/config.dart'; |
| import 'package:flutter_tools/src/base/file_system.dart'; |
| import 'package:flutter_tools/src/base/platform.dart'; |
| import 'package:flutter_tools/src/base/version.dart'; |
| import 'package:flutter_tools/src/globals.dart' as globals; |
| import 'package:flutter_tools/src/ios/plist_parser.dart'; |
| import 'package:test/fake.dart'; |
| |
| import '../../src/common.dart'; |
| import '../../src/context.dart'; |
| import '../../src/fake_process_manager.dart'; |
| |
| void main() { |
| |
| group('installation detection on MacOS', () { |
| const String homeMac = '/Users/me'; |
| |
| const Map<String, Object> macStudioInfoPlist3_3 = <String, Object>{ |
| 'CFBundleGetInfoString': 'Android Studio 3.3, build AI-182.5107.16.33.5199772. Copyright JetBrains s.r.o., (c) 2000-2018', |
| 'CFBundleShortVersionString': '3.3', |
| 'CFBundleVersion': 'AI-182.5107.16.33.5199772', |
| 'JVMOptions': <String, Object>{ |
| 'Properties': <String, Object>{ |
| 'idea.paths.selector': 'AndroidStudio3.3', |
| 'idea.platform.prefix': 'AndroidStudio', |
| }, |
| }, |
| }; |
| |
| const Map<String, Object> macStudioInfoPlist4_1 = <String, Object>{ |
| 'CFBundleGetInfoString': 'Android Studio 4.1, build AI-201.8743.12.41.6858069. Copyright JetBrains s.r.o., (c) 2000-2020', |
| 'CFBundleShortVersionString': '4.1', |
| 'CFBundleVersion': 'AI-201.8743.12.41.6858069', |
| 'JVMOptions': <String, Object>{ |
| 'Properties': <String, Object>{ |
| 'idea.vendor.name' : 'Google', |
| 'idea.paths.selector': 'AndroidStudio4.1', |
| 'idea.platform.prefix': 'AndroidStudio', |
| }, |
| }, |
| }; |
| |
| const Map<String, Object> macStudioInfoPlist2020_3 = <String, Object>{ |
| 'CFBundleGetInfoString': 'Android Studio 2020.3, build AI-203.7717.56.2031.7583922. Copyright JetBrains s.r.o., (c) 2000-2021', |
| 'CFBundleShortVersionString': '2020.3', |
| 'CFBundleVersion': 'AI-203.7717.56.2031.7583922', |
| 'JVMOptions': <String, Object>{ |
| 'Properties': <String, Object>{ |
| 'idea.vendor.name' : 'Google', |
| 'idea.paths.selector': 'AndroidStudio2020.3', |
| 'idea.platform.prefix': 'AndroidStudio', |
| }, |
| }, |
| }; |
| |
| const Map<String, Object> macStudioInfoPlist2022_1 = <String, Object>{ |
| 'CFBundleGetInfoString': 'Android Studio 2022.1, build AI-221.6008.13.2211.9477386. Copyright JetBrains s.r.o., (c) 2000-2023', |
| 'CFBundleShortVersionString': '2022.1', |
| 'CFBundleVersion': 'AI-221.6008.13.2211.9477386', |
| 'JVMOptions': <String, Object>{ |
| 'Properties': <String, Object>{ |
| 'idea.vendor.name' : 'Google', |
| 'idea.paths.selector': 'AndroidStudio2022.1', |
| 'idea.platform.prefix': 'AndroidStudio', |
| }, |
| }, |
| }; |
| |
| const Map<String, Object> macStudioInfoPlistEap_2022_3_1_11 = <String, Object>{ |
| 'CFBundleGetInfoString': 'Android Studio EAP AI-223.8836.35.2231.9848316, build AI-223.8836.35.2231.9848316. Copyright JetBrains s.r.o., (c) 2000-2023', |
| 'CFBundleShortVersionString': 'EAP AI-223.8836.35.2231.9848316', |
| 'CFBundleVersion': 'AI-223.8836.35.2231.9848316', |
| 'JVMOptions': <String, Object>{ |
| 'Properties': <String, Object>{ |
| 'idea.vendor.name' : 'Google', |
| 'idea.paths.selector': 'AndroidStudioPreview2022.3', |
| 'idea.platform.prefix': 'AndroidStudio', |
| }, |
| }, |
| }; |
| |
| late Config config; |
| late FileSystem fileSystem; |
| late FileSystemUtils fsUtils; |
| late Platform platform; |
| late FakePlistUtils plistUtils; |
| late FakeProcessManager processManager; |
| |
| setUp(() { |
| config = Config.test(); |
| fileSystem = MemoryFileSystem.test(); |
| plistUtils = FakePlistUtils(); |
| platform = FakePlatform( |
| operatingSystem: 'macos', |
| environment: <String, String>{'HOME': homeMac}, |
| ); |
| fsUtils = FileSystemUtils( |
| fileSystem: fileSystem, |
| platform: platform, |
| ); |
| processManager = FakeProcessManager.empty(); |
| }); |
| |
| testUsingContext('discovers Android Studio >=4.1 location', () { |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Application', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[plistFilePath] = macStudioInfoPlist4_1; |
| processManager.addCommand(FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(studioInApplicationPlistFolder, 'jre', 'jdk', 'Contents', 'Home', 'bin', 'java'), |
| '-version', |
| ], |
| stderr: '123', |
| ) |
| ); |
| final AndroidStudio studio = AndroidStudio.fromMacOSBundle( |
| fileSystem.directory(studioInApplicationPlistFolder).parent.path, |
| )!; |
| |
| expect(studio, isNotNull); |
| expect(studio.pluginsPath, equals(fileSystem.path.join( |
| homeMac, |
| 'Library', |
| 'Application Support', |
| 'Google', |
| 'AndroidStudio4.1', |
| ))); |
| expect(studio.validationMessages, <String>['Java version 123']); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => processManager, |
| // Custom home paths are not supported on macOS nor Windows yet, |
| // so we force the platform to fake Linux here. |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('discovers Android Studio >=2020.3 location', () { |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Application', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[plistFilePath] = macStudioInfoPlist2020_3; |
| processManager.addCommand(FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(studioInApplicationPlistFolder, 'jre', 'Contents', 'Home', 'bin', 'java'), |
| '-version', |
| ], |
| stderr: '123', |
| ) |
| ); |
| final AndroidStudio studio = AndroidStudio.fromMacOSBundle( |
| fileSystem.directory(studioInApplicationPlistFolder).parent.path, |
| )!; |
| |
| expect(studio, isNotNull); |
| expect(studio.pluginsPath, equals(fileSystem.path.join( |
| homeMac, |
| 'Library', |
| 'Application Support', |
| 'Google', |
| 'AndroidStudio2020.3', |
| ))); |
| expect(studio.validationMessages, <String>['Java version 123']); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => processManager, |
| // Custom home paths are not supported on macOS nor Windows yet, |
| // so we force the platform to fake Linux here. |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('discovers Android Studio <4.1 location', () { |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Application', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[plistFilePath] = macStudioInfoPlist3_3; |
| processManager.addCommand(FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(studioInApplicationPlistFolder, 'jre', 'jdk', 'Contents', 'Home', 'bin', 'java'), |
| '-version', |
| ], |
| stderr: '123', |
| ) |
| ); |
| final AndroidStudio studio = AndroidStudio.fromMacOSBundle( |
| fileSystem.directory(studioInApplicationPlistFolder).parent.path, |
| )!; |
| |
| expect(studio, isNotNull); |
| expect(studio.pluginsPath, equals(fileSystem.path.join( |
| homeMac, |
| 'Library', |
| 'Application Support', |
| 'AndroidStudio3.3', |
| ))); |
| expect(studio.validationMessages, <String>['Java version 123']); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => processManager, |
| // Custom home paths are not supported on macOS nor Windows yet, |
| // so we force the platform to fake Linux here. |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('discovers Android Studio EAP location', () { |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Application', |
| 'Android Studio with suffix.app', |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[plistFilePath] = macStudioInfoPlistEap_2022_3_1_11; |
| processManager.addCommand(FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(studioInApplicationPlistFolder, 'jbr', 'Contents', 'Home', 'bin', 'java'), |
| '-version', |
| ], |
| stderr: '123', |
| ) |
| ); |
| final AndroidStudio studio = AndroidStudio.fromMacOSBundle( |
| fileSystem.directory(studioInApplicationPlistFolder).parent.path, |
| )!; |
| |
| expect(studio, isNotNull); |
| expect(studio.pluginsPath, equals(fileSystem.path.join( |
| homeMac, |
| 'Library', |
| 'Application Support', |
| 'AndroidStudioPreview2022.3', |
| ))); |
| expect(studio.validationMessages, <String>['Java version 123']); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => processManager, |
| // Custom home paths are not supported on macOS nor Windows yet, |
| // so we force the platform to fake Linux here. |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('does not discover Android Studio with JetBrainsToolboxApp wrapper', () { |
| final String applicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Applications', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(applicationPlistFolder).createSync(recursive: true); |
| |
| final String applicationsPlistFilePath = fileSystem.path.join(applicationPlistFolder, 'Info.plist'); |
| const Map<String, Object> jetbrainsInfoPlist = <String, Object>{ |
| 'JetBrainsToolboxApp': 'ignored', |
| }; |
| plistUtils.fileContents[applicationsPlistFilePath] = jetbrainsInfoPlist; |
| |
| final String homeDirectoryPlistFolder = fileSystem.path.join( |
| fsUtils.homeDirPath!, |
| 'Applications', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(homeDirectoryPlistFolder).createSync(recursive: true); |
| |
| final String homeDirectoryPlistFilePath = fileSystem.path.join(homeDirectoryPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[homeDirectoryPlistFilePath] = macStudioInfoPlist2020_3; |
| |
| expect(AndroidStudio.allInstalled().length, 1); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => FakeProcessManager.any(), |
| // Custom home paths are not supported on macOS nor Windows yet, |
| // so we force the platform to fake Linux here. |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('discovers installation from Spotlight query', () { |
| // One in expected location. |
| final String studioInApplication = fileSystem.path.join( |
| '/', |
| 'Application', |
| 'Android Studio.app', |
| ); |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| studioInApplication, |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[plistFilePath] = macStudioInfoPlist4_1; |
| |
| // Two in random location only Spotlight knows about. |
| final String randomLocation1 = fileSystem.path.join( |
| '/', |
| 'random', |
| 'Android Studio Preview.app', |
| ); |
| final String randomLocation1PlistFolder = fileSystem.path.join( |
| randomLocation1, |
| 'Contents', |
| ); |
| fileSystem.directory(randomLocation1PlistFolder).createSync(recursive: true); |
| final String randomLocation1PlistPath = fileSystem.path.join(randomLocation1PlistFolder, 'Info.plist'); |
| plistUtils.fileContents[randomLocation1PlistPath] = macStudioInfoPlist4_1; |
| |
| final String randomLocation2 = fileSystem.path.join( |
| '/', |
| 'random', |
| 'Android Studio with Blaze.app', |
| ); |
| final String randomLocation2PlistFolder = fileSystem.path.join( |
| randomLocation2, |
| 'Contents', |
| ); |
| fileSystem.directory(randomLocation2PlistFolder).createSync(recursive: true); |
| final String randomLocation2PlistPath = fileSystem.path.join(randomLocation2PlistFolder, 'Info.plist'); |
| plistUtils.fileContents[randomLocation2PlistPath] = macStudioInfoPlist4_1; |
| final String javaBin = fileSystem.path.join('jre', 'jdk', 'Contents', 'Home', 'bin', 'java'); |
| |
| // Spotlight finds the one known and two random installations. |
| processManager.addCommands(<FakeCommand>[ |
| FakeCommand( |
| command: const <String>[ |
| 'mdfind', |
| 'kMDItemCFBundleIdentifier="com.google.android.studio*"', |
| ], |
| stdout: '$randomLocation1\n$randomLocation2\n$studioInApplication', |
| ), |
| FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(randomLocation1, 'Contents', javaBin), |
| '-version', |
| ], |
| ), |
| FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(randomLocation2, 'Contents', javaBin), |
| '-version', |
| ], |
| ), |
| FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(studioInApplicationPlistFolder, javaBin), |
| '-version', |
| ], |
| ), |
| ]); |
| |
| // Results are de-duplicated, only 3 installed. |
| expect(AndroidStudio.allInstalled().length, 3); |
| expect(processManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => processManager, |
| // Custom home paths are not supported on macOS nor Windows yet, |
| // so we force the platform to fake Linux here. |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('finds latest valid install', () { |
| final String applicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Applications', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(applicationPlistFolder).createSync(recursive: true); |
| |
| final String applicationsPlistFilePath = fileSystem.path.join(applicationPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[applicationsPlistFilePath] = macStudioInfoPlist3_3; |
| |
| final String homeDirectoryPlistFolder = fileSystem.path.join( |
| fsUtils.homeDirPath!, |
| 'Applications', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(homeDirectoryPlistFolder).createSync(recursive: true); |
| |
| final String homeDirectoryPlistFilePath = fileSystem.path.join(homeDirectoryPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[homeDirectoryPlistFilePath] = macStudioInfoPlist4_1; |
| |
| expect(AndroidStudio.allInstalled().length, 2); |
| expect(AndroidStudio.latestValid()!.version, Version(4, 1, 0)); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => FakeProcessManager.any(), |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('extracts custom paths for directly downloaded Android Studio', () { |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Application', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[plistFilePath] = macStudioInfoPlist3_3; |
| final AndroidStudio studio = AndroidStudio.fromMacOSBundle( |
| fileSystem.directory(studioInApplicationPlistFolder).parent.path, |
| )!; |
| expect(studio, isNotNull); |
| expect(studio.pluginsPath, equals(fileSystem.path.join( |
| homeMac, |
| 'Library', |
| 'Application Support', |
| 'AndroidStudio3.3', |
| ))); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => FakeProcessManager.any(), |
| // Custom home paths are not supported on macOS nor Windows yet, |
| // so we force the platform to fake Linux here. |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('finds Android Studio 2020.3 bundled Java version', () { |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Application', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[plistFilePath] = macStudioInfoPlist2020_3; |
| processManager.addCommand(FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(studioInApplicationPlistFolder, 'jre', 'Contents', 'Home', 'bin', 'java'), |
| '-version', |
| ], |
| stderr: '123', |
| ) |
| ); |
| final AndroidStudio studio = AndroidStudio.fromMacOSBundle( |
| fileSystem.directory(studioInApplicationPlistFolder).parent.path, |
| )!; |
| |
| expect(studio.javaPath, equals(fileSystem.path.join( |
| studioInApplicationPlistFolder, |
| 'jre', |
| 'Contents', |
| 'Home', |
| ))); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => processManager, |
| // Custom home paths are not supported on macOS nor Windows yet, |
| // so we force the platform to fake Linux here. |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('finds Android Studio 2022.1 bundled Java version', () { |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Application', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[plistFilePath] = macStudioInfoPlist2022_1; |
| processManager.addCommand(FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(studioInApplicationPlistFolder, 'jbr', 'Contents', 'Home', 'bin', 'java'), |
| '-version', |
| ], |
| stderr: '123', |
| ) |
| ); |
| final AndroidStudio studio = AndroidStudio.fromMacOSBundle( |
| fileSystem.directory(studioInApplicationPlistFolder).parent.path, |
| )!; |
| |
| expect(studio.javaPath, equals(fileSystem.path.join( |
| studioInApplicationPlistFolder, |
| 'jbr', |
| 'Contents', |
| 'Home', |
| ))); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => processManager, |
| // Custom home paths are not supported on macOS nor Windows yet, |
| // so we force the platform to fake Linux here. |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('finds bundled Java version when Android Studio version is unknown by assuming the latest version', () { |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Application', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| final Map<String, Object> plistWithoutVersion = Map<String, Object>.from(macStudioInfoPlist2022_1); |
| plistWithoutVersion['CFBundleShortVersionString'] = ''; |
| plistUtils.fileContents[plistFilePath] = plistWithoutVersion; |
| |
| final String jdkPath = fileSystem.path.join(studioInApplicationPlistFolder, 'jbr', 'Contents', 'Home'); |
| |
| processManager.addCommand(FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(jdkPath, 'bin', 'java'), |
| '-version', |
| ], |
| stderr: '123', |
| ) |
| ); |
| final AndroidStudio studio = AndroidStudio.fromMacOSBundle( |
| fileSystem.directory(studioInApplicationPlistFolder).parent.path, |
| )!; |
| |
| expect(studio.version, null); |
| expect(studio.javaPath, jdkPath); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => processManager, |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('when given an Android Studio newer than any known version, finds Java version by assuming latest known Android Studio version', () { |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| '/', |
| 'Application', |
| 'Android Studio.app', |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| final Map<String, Object> plistWithoutVersion = Map<String, Object>.from(macStudioInfoPlist2022_1); |
| plistWithoutVersion['CFBundleShortVersionString'] = '99999.99.99'; |
| plistUtils.fileContents[plistFilePath] = plistWithoutVersion; |
| |
| final String jdkPathFor2022 = fileSystem.path.join(studioInApplicationPlistFolder, 'jbr', 'Contents', 'Home'); |
| |
| final AndroidStudio studio = AndroidStudio.fromMacOSBundle( |
| fileSystem.directory(studioInApplicationPlistFolder).parent.path, |
| )!; |
| |
| expect(studio.version, equals(Version(99999, 99, 99))); |
| expect(studio.javaPath, jdkPathFor2022); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => FakeProcessManager.any(), |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| |
| testUsingContext('discovers explicitly configured Android Studio', () { |
| final String extractedDownloadZip = fileSystem.path.join( |
| '/', |
| 'Users', |
| 'Dash', |
| 'Desktop', |
| 'android-studio' |
| ); |
| config.setValue('android-studio-dir', extractedDownloadZip); |
| final String studioInApplicationPlistFolder = fileSystem.path.join( |
| extractedDownloadZip, |
| 'Contents', |
| ); |
| fileSystem.directory(studioInApplicationPlistFolder).createSync(recursive: true); |
| final String plistFilePath = fileSystem.path.join(studioInApplicationPlistFolder, 'Info.plist'); |
| plistUtils.fileContents[plistFilePath] = macStudioInfoPlist2022_1; |
| |
| final String studioInApplicationJavaBinary = fileSystem.path.join( |
| extractedDownloadZip, |
| 'Contents', 'jbr', 'Contents', 'Home', 'bin', 'java', |
| ); |
| |
| processManager.addCommands(<FakeCommand>[ |
| FakeCommand( |
| command: const <String>[ |
| 'mdfind', |
| 'kMDItemCFBundleIdentifier="com.google.android.studio*"', |
| ], |
| stdout: extractedDownloadZip, |
| ), |
| FakeCommand( |
| command: <String>[ |
| studioInApplicationJavaBinary, |
| '-version', |
| ], |
| ), |
| ]); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.configuredPath, extractedDownloadZip); |
| expect(processManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| Config:() => config, |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| ProcessManager: () => processManager, |
| Platform: () => platform, |
| PlistParser: () => plistUtils, |
| }); |
| }); |
| |
| group('installation detection on Windows', () { |
| late Config config; |
| late Platform platform; |
| late FileSystem fileSystem; |
| |
| setUp(() { |
| config = Config.test(); |
| platform = FakePlatform( |
| operatingSystem: 'windows', |
| environment: <String, String>{ |
| 'LOCALAPPDATA': r'C:\Users\Dash\AppData\Local', |
| } |
| ); |
| fileSystem = MemoryFileSystem.test(style: FileSystemStyle.windows); |
| }); |
| |
| testUsingContext('discovers Android Studio 4.1 location', () { |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio4.1\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(r'C:\Program Files\AndroidStudio'); |
| fileSystem.directory(r'C:\Program Files\AndroidStudio') |
| .createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, Version(4, 1, 0)); |
| expect(studio.studioAppName, 'Android Studio'); |
| }, overrides: <Type, Generator>{ |
| Platform: () => platform, |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('discovers Android Studio 4.2 location', () { |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio4.2\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(r'C:\Program Files\AndroidStudio'); |
| fileSystem.directory(r'C:\Program Files\AndroidStudio') |
| .createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, Version(4, 2, 0)); |
| expect(studio.studioAppName, 'Android Studio'); |
| }, overrides: <Type, Generator>{ |
| Platform: () => platform, |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('discovers Android Studio 2020.3 location', () { |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio2020.3\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(r'C:\Program Files\AndroidStudio'); |
| fileSystem.directory(r'C:\Program Files\AndroidStudio') |
| .createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, Version(2020, 3, 0)); |
| expect(studio.studioAppName, 'Android Studio'); |
| }, overrides: <Type, Generator>{ |
| Platform: () => platform, |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('does not discover Android Studio 4.1 location if LOCALAPPDATA is null', () { |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio4.1\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(r'C:\Program Files\AndroidStudio'); |
| fileSystem.directory(r'C:\Program Files\AndroidStudio') |
| .createSync(recursive: true); |
| |
| expect(AndroidStudio.allInstalled(), isEmpty); |
| }, overrides: <Type, Generator>{ |
| Platform: () => FakePlatform( |
| operatingSystem: 'windows', |
| environment: <String, String>{}, // Does not include LOCALAPPDATA |
| ), |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('does not discover Android Studio 4.2 location if LOCALAPPDATA is null', () { |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio4.2\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(r'C:\Program Files\AndroidStudio'); |
| fileSystem.directory(r'C:\Program Files\AndroidStudio') |
| .createSync(recursive: true); |
| |
| expect(AndroidStudio.allInstalled(), isEmpty); |
| }, overrides: <Type, Generator>{ |
| Platform: () => FakePlatform( |
| operatingSystem: 'windows', |
| environment: <String, String>{}, // Does not include LOCALAPPDATA |
| ), |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('does not discover Android Studio 2020.3 location if LOCALAPPDATA is null', () { |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio2020.3\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(r'C:\Program Files\AndroidStudio'); |
| fileSystem.directory(r'C:\Program Files\AndroidStudio') |
| .createSync(recursive: true); |
| |
| expect(AndroidStudio.allInstalled(), isEmpty); |
| }, overrides: <Type, Generator>{ |
| Platform: () => FakePlatform( |
| operatingSystem: 'windows', |
| environment: <String, String>{}, // Does not include LOCALAPPDATA |
| ), |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('finds Android Studio 2020.3 bundled Java version', () { |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio2020.3\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(r'C:\Program Files\AndroidStudio'); |
| fileSystem.directory(r'C:\Program Files\AndroidStudio') |
| .createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.javaPath, equals(r'C:\Program Files\AndroidStudio\jre')); |
| }, overrides: <Type, Generator>{ |
| Platform: () => platform, |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('finds Android Studio 2022.1 bundled Java version', () { |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio2022.1\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(r'C:\Program Files\AndroidStudio'); |
| fileSystem.directory(r'C:\Program Files\AndroidStudio') |
| .createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.javaPath, equals(r'C:\Program Files\AndroidStudio\jbr')); |
| }, overrides: <Type, Generator>{ |
| Platform: () => platform, |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('finds bundled Java version when Android Studio version is unknown by assuming the latest version', () { |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(r'C:\Program Files\AndroidStudio'); |
| fileSystem.directory(r'C:\Program Files\AndroidStudio') |
| .createSync(recursive: true); |
| |
| fileSystem.file(r'C:\Program Files\AndroidStudio\jbr\bin\java').createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, null); |
| expect(studio.javaPath, equals(r'C:\Program Files\AndroidStudio\jbr')); |
| }, overrides: <Type, Generator>{ |
| Platform: () => platform, |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('when given an Android Studio newer than any known version, finds Java version by assuming latest known Android Studio version', () { |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio99999.99.99\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(r'C:\Program Files\AndroidStudio'); |
| fileSystem.directory(r'C:\Program Files\AndroidStudio') |
| .createSync(recursive: true); |
| |
| fileSystem.file(r'C:\Program Files\AndroidStudio\jbr\bin\java').createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| const String expectedJdkLocationFor2022 = r'C:\Program Files\AndroidStudio\jbr'; |
| expect(studio.version, equals(Version(99999, 99, 99))); |
| expect(studio.javaPath, equals(expectedJdkLocationFor2022)); |
| }, overrides: <Type, Generator>{ |
| Platform: () => platform, |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('discovers explicitly configured Android Studio', () { |
| const String androidStudioDir = r'C:\Users\Dash\Desktop\android-studio'; |
| config.setValue('android-studio-dir', androidStudioDir); |
| fileSystem.file(r'C:\Users\Dash\AppData\Local\Google\AndroidStudio2022.1\.home') |
| ..createSync(recursive: true) |
| ..writeAsStringSync(androidStudioDir); |
| fileSystem.directory(androidStudioDir) |
| .createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, equals(Version(2022, 1, null))); |
| expect(studio.configuredPath, androidStudioDir); |
| expect(studio.javaPath, fileSystem.path.join(androidStudioDir, 'jbr')); |
| }, overrides: <Type, Generator>{ |
| Config: () => config, |
| Platform: () => platform, |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| }); |
| |
| group('installation detection on Linux', () { |
| const String homeLinux = '/home/me'; |
| |
| late Config config; |
| late FileSystem fileSystem; |
| late FileSystemUtils fsUtils; |
| late Platform platform; |
| |
| setUp(() { |
| config = Config.test(); |
| platform = FakePlatform( |
| environment: <String, String>{'HOME': homeLinux}, |
| ); |
| fileSystem = MemoryFileSystem.test(); |
| fsUtils = FileSystemUtils( |
| fileSystem: fileSystem, |
| platform: platform, |
| ); |
| }); |
| |
| testUsingContext('discovers Android Studio <4.1', () { |
| const String studioHomeFilePath = |
| '$homeLinux/.AndroidStudio4.0/system/.home'; |
| const String studioInstallPath = '$homeLinux/AndroidStudio'; |
| |
| fileSystem.file(studioHomeFilePath) |
| ..createSync(recursive: true) |
| ..writeAsStringSync(studioInstallPath); |
| |
| fileSystem.directory(studioInstallPath).createSync(); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, Version(4, 0, 0)); |
| expect(studio.studioAppName, 'AndroidStudio'); |
| expect( |
| studio.pluginsPath, |
| '/home/me/.AndroidStudio4.0/config/plugins', |
| ); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| Platform: () => platform, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('discovers Android Studio >=4.1', () { |
| const String studioHomeFilePath = |
| '$homeLinux/.cache/Google/AndroidStudio4.1/.home'; |
| const String studioInstallPath = '$homeLinux/AndroidStudio'; |
| |
| fileSystem.file(studioHomeFilePath) |
| ..createSync(recursive: true) |
| ..writeAsStringSync(studioInstallPath); |
| |
| fileSystem.directory(studioInstallPath).createSync(); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, Version(4, 1, 0)); |
| expect(studio.studioAppName, 'AndroidStudio'); |
| expect( |
| studio.pluginsPath, |
| '/home/me/.local/share/Google/AndroidStudio4.1', |
| ); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| Platform: () => platform, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('discovers when installed with Toolbox', () { |
| const String studioHomeFilePath = |
| '$homeLinux/.cache/Google/AndroidStudio4.1/.home'; |
| const String studioInstallPath = |
| '$homeLinux/.local/share/JetBrains/Toolbox/apps/AndroidStudio/ch-0/201.7042882'; |
| const String pluginsInstallPath = '$studioInstallPath.plugins'; |
| |
| fileSystem.file(studioHomeFilePath) |
| ..createSync(recursive: true) |
| ..writeAsStringSync(studioInstallPath); |
| |
| fileSystem.directory(studioInstallPath).createSync(recursive: true); |
| fileSystem.directory(pluginsInstallPath).createSync(); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, Version(4, 1, 0)); |
| expect(studio.studioAppName, 'AndroidStudio'); |
| expect( |
| studio.pluginsPath, |
| pluginsInstallPath, |
| ); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| Platform: () => platform, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('finds Android Studio 2020.3 bundled Java version', () { |
| const String studioHomeFilePath = '$homeLinux/.cache/Google/AndroidStudio2020.3/.home'; |
| const String studioInstallPath = '$homeLinux/AndroidStudio'; |
| |
| fileSystem.file(studioHomeFilePath) |
| ..createSync(recursive: true) |
| ..writeAsStringSync(studioInstallPath); |
| |
| fileSystem.directory(studioInstallPath).createSync(); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.javaPath, equals('$studioInstallPath/jre')); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| Platform: () => platform, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('finds Android Studio 2022.1 bundled Java version', () { |
| const String studioHomeFilePath = |
| '$homeLinux/.cache/Google/AndroidStudio2022.1/.home'; |
| const String studioInstallPath = '$homeLinux/AndroidStudio'; |
| |
| fileSystem.file(studioHomeFilePath) |
| ..createSync(recursive: true) |
| ..writeAsStringSync(studioInstallPath); |
| |
| fileSystem.directory(studioInstallPath).createSync(); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.javaPath, equals('$studioInstallPath/jbr')); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| Platform: () => platform, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('finds bundled Java version when Android Studio version is unknown by assuming the latest version', () { |
| const String configuredStudioInstallPath = '$homeLinux/AndroidStudio'; |
| config.setValue('android-studio-dir', configuredStudioInstallPath); |
| |
| fileSystem.directory(configuredStudioInstallPath).createSync(recursive: true); |
| |
| fileSystem.directory(configuredStudioInstallPath).createSync(); |
| |
| fileSystem.file(fileSystem.path.join(configuredStudioInstallPath, 'jbr', 'bin', 'java')).createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, null); |
| expect(studio.javaPath, equals('$configuredStudioInstallPath/jbr')); |
| }, overrides: <Type, Generator>{ |
| Config: () => config, |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| Platform: () => platform, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('when given an Android Studio newer than any known version, finds Java version by assuming latest known Android Studio version', () { |
| const String studioHomeFilePath = |
| '$homeLinux/.cache/Google/AndroidStudio99999.99.99/.home'; |
| const String studioInstallPath = '$homeLinux/AndroidStudio'; |
| |
| fileSystem.file(studioHomeFilePath) |
| ..createSync(recursive: true) |
| ..writeAsStringSync(studioInstallPath); |
| |
| fileSystem.directory(studioInstallPath).createSync(); |
| |
| final String expectedJdkLocationFor2022 = fileSystem.path.join(studioInstallPath, 'jbr', 'bin', 'java'); |
| fileSystem.file(expectedJdkLocationFor2022).createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, equals(Version(99999, 99, 99))); |
| expect(studio.javaPath, equals('$studioInstallPath/jbr')); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| FileSystemUtils: () => fsUtils, |
| Platform: () => platform, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('pluginsPath extracts custom paths from home dir', () { |
| const String installPath = '/opt/android-studio-with-cheese-5.0'; |
| const String studioHome = '$homeLinux/.AndroidStudioWithCheese5.0'; |
| const String homeFile = '$studioHome/system/.home'; |
| fileSystem.directory(installPath).createSync(recursive: true); |
| fileSystem.file(homeFile).createSync(recursive: true); |
| fileSystem.file(homeFile).writeAsStringSync(installPath); |
| |
| final AndroidStudio studio = |
| AndroidStudio.fromHomeDot(fileSystem.directory(studioHome))!; |
| expect(studio, isNotNull); |
| expect(studio.pluginsPath, |
| equals('/home/me/.AndroidStudioWithCheese5.0/config/plugins')); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| // Custom home paths are not supported on macOS nor Windows yet, |
| // so we force the platform to fake Linux here. |
| Platform: () => platform, |
| FileSystemUtils: () => FileSystemUtils( |
| fileSystem: fileSystem, |
| platform: platform, |
| ), |
| }); |
| |
| testUsingContext('discovers explicitly configured Android Studio', () { |
| const String androidStudioDir = '/Users/Dash/Desktop/android-studio'; |
| config.setValue('android-studio-dir', androidStudioDir); |
| const String studioHome = '$homeLinux/.cache/Google/AndroidStudio2022.3/.home'; |
| fileSystem.file(studioHome) |
| ..createSync(recursive: true) |
| ..writeAsStringSync(androidStudioDir); |
| fileSystem.directory(androidStudioDir) |
| .createSync(recursive: true); |
| |
| final AndroidStudio studio = AndroidStudio.allInstalled().single; |
| |
| expect(studio.version, equals(Version(2022, 3, null))); |
| expect(studio.configuredPath, androidStudioDir); |
| expect(studio.javaPath, fileSystem.path.join(androidStudioDir, 'jbr')); |
| }, overrides: <Type, Generator>{ |
| Config: () => config, |
| Platform: () => platform, |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| }); |
| |
| group('latestValid', () { |
| late Config config; |
| late Platform platform; |
| late FileSystem fileSystem; |
| |
| setUp(() { |
| config = Config.test(); |
| 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'; |
| 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, 'jbr', '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>[ |
| fileSystem.path.join(javaPath), |
| '-version', |
| ], |
| )); |
| } |
| |
| expect(AndroidStudio.allInstalled().length, 4); |
| |
| for (final String javaPath in validJavaPaths) { |
| (globals.processManager as FakeProcessManager).addCommand(FakeCommand( |
| command: <String>[ |
| fileSystem.path.join(javaPath), |
| '-version', |
| ], |
| )); |
| } |
| |
| final AndroidStudio chosenInstall = AndroidStudio.latestValid()!; |
| expect(chosenInstall.directory, configuredAndroidStudioDir); |
| expect(chosenInstall.isValid, false); |
| }, overrides: <Type, Generator>{ |
| Config: () => config, |
| 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'; |
| 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, |
| FileSystem: () => fileSystem, |
| Platform: () => platform, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('handles file system exception when checking for explicitly configured Android Studio install', () { |
| const String androidStudioDir = '/Users/Dash/Desktop/android-studio'; |
| config.setValue('android-studio-dir', androidStudioDir); |
| |
| expect(() => AndroidStudio.latestValid(), |
| throwsToolExit(message: RegExp(r'[.\s\S]*Could not find[.\s\S]*FileSystemException[.\s\S]*'))); |
| }, overrides: <Type, Generator>{ |
| Config: () => config, |
| Platform: () => platform, |
| FileSystem: () => _FakeFileSystem(), |
| FileSystemUtils: () => _FakeFsUtils(), |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| }); |
| } |
| |
| class FakePlistUtils extends Fake implements PlistParser { |
| final Map<String, Map<String, Object>> fileContents = <String, Map<String, Object>>{}; |
| |
| @override |
| Map<String, Object> parseFile(String plistFilePath) { |
| return fileContents[plistFilePath]!; |
| } |
| } |
| |
| class _FakeFileSystem extends Fake implements FileSystem { |
| @override |
| Directory directory(dynamic path) { |
| return _NonExistentDirectory(); |
| } |
| |
| @override |
| Context get path { |
| return MemoryFileSystem.test().path; |
| } |
| } |
| |
| class _NonExistentDirectory extends Fake implements Directory { |
| @override |
| bool existsSync() { |
| throw const FileSystemException('OS Error: Filename, directory name, or volume label syntax is incorrect.'); |
| } |
| |
| @override |
| String get path => ''; |
| |
| @override |
| Directory get parent => _NonExistentDirectory(); |
| } |
| |
| class _FakeFsUtils extends Fake implements FileSystemUtils { |
| @override |
| String get homeDirPath => '/home/'; |
| } |